package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.data.service.CabinetFileService;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasCommentEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.PaasProcessTaskEntity;
import com.xbongbong.paas.domain.entity.StageLogEntity;
import com.xbongbong.paas.domain.entity.ext.PaasAttachmentEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasCommentEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessNodeTaskEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.NodeTypeEnum;
import com.xbongbong.paas.enums.ProcessTypeEnum;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.help.StageDetailHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.thread.LogThreadPoolBeanConfig;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasCommentModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.model.PaasProcessDataModel;
import com.xbongbong.paas.model.PaasProcessNodeTaskModel;
import com.xbongbong.paas.model.PaasProcessTaskModel;
import com.xbongbong.paas.model.StageLogModel;
import com.xbongbong.paas.pojo.CommentPojo;
import com.xbongbong.paas.pojo.dto.CommentAddDTO;
import com.xbongbong.paas.pojo.dto.CommentAddOnCommentDTO;
import com.xbongbong.paas.pojo.dto.CommentDeleteDTO;
import com.xbongbong.paas.pojo.dto.CommentDetailDTO;
import com.xbongbong.paas.pojo.dto.CommentEditDTO;
import com.xbongbong.paas.pojo.dto.CommentListDTO;
import com.xbongbong.paas.pojo.dto.FormDataGetDTO;
import com.xbongbong.paas.pojo.dto.ReplyListDTO;
import com.xbongbong.paas.pojo.dto.UserGetDTO;
import com.xbongbong.paas.pojo.vo.CommentAddOnCommentVO;
import com.xbongbong.paas.pojo.vo.CommentAddVO;
import com.xbongbong.paas.pojo.vo.CommentDeleteVO;
import com.xbongbong.paas.pojo.vo.CommentListVO;
import com.xbongbong.paas.pojo.vo.ReplyListVO;
import com.xbongbong.paas.pojo.vo.UserGetVO;
import com.xbongbong.paas.service.PaasCommentService;
import com.xbongbong.paas.service.PaasFormService;
import com.xbongbong.paas.service.UserService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.CommentHelp;
import com.xbongbong.paas.toolbox.pojo.DataPermissionParamsPojo;
import com.xbongbong.paas.toolbox.thread.TransmittableThreadLocalUtil;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.cabinetfile.pojo.dto.CabinetFileSaveDTO;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.CabinetFileTypeEnum;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.PrintErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.log.enums.DetailLogEnum;
import com.xbongbong.pro.log.pojo.DetailLogPojo;
import com.xbongbong.pro.message.constant.ApprovalPushConstant;
import com.xbongbong.pro.message.constant.ClueStagePushConstant;
import com.xbongbong.pro.message.constant.CommunicatePushConstant;
import com.xbongbong.pro.message.constant.ContractStagePushConstant;
import com.xbongbong.pro.message.constant.CustomerStagePushConstant;
import com.xbongbong.pro.message.constant.DistributorCommunicatePushConstant;
import com.xbongbong.pro.message.constant.OpportunityStagePushConstant;
import com.xbongbong.pro.message.constant.PaasStagePushConstant;
import com.xbongbong.pro.message.constant.ProcessPushConstant;
import com.xbongbong.pro.message.constant.WorkOrderPushConstant;
import com.xbongbong.pro.message.constant.WorkReportPushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.message.service.MessageService;
import com.xbongbong.pro.rabbitmq.producer.BaseProducer;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.constant.comment.PaasCommentConstant;
import com.xbongbong.saas.domain.entity.ClueStageLogEntity;
import com.xbongbong.saas.domain.entity.CustomerStageLogEntity;
import com.xbongbong.saas.domain.entity.OpportunityStageLogEntity;
import com.xbongbong.saas.domain.entity.ext.OpportunityEntityExt;
import com.xbongbong.saas.domain.entity.ext.WorkOrderFormEntityExt;
import com.xbongbong.saas.enums.BusinessCommentEnum;
import com.xbongbong.saas.enums.ClueRuleSettingEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.RuleSettingEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.CustomerCommunicateEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.DistributorCommunicateEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.enums.business.SupplierCommunicateEnum;
import com.xbongbong.saas.enums.business.WorkReportFieldEnum;
import com.xbongbong.saas.enums.business.WorkReportTypeEnum;
import com.xbongbong.saas.help.ProcessHelp;
import com.xbongbong.saas.help.SaasGetHelp;
import com.xbongbong.saas.model.ClueModel;
import com.xbongbong.saas.model.ClueStageLogModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.CustomerStageLogModel;
import com.xbongbong.saas.model.OpportunityModel;
import com.xbongbong.saas.model.OpportunityStageLogModel;
import com.xbongbong.saas.model.PaasFormDataModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.saas.service.LikeService;
import com.xbongbong.saas.service.ScoreCalculateService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getIntegerOrDefaultFromFormData;

/**
 * @author: wufeng
 * @date: 2018/8/29 10:02
 * @desrcption:
 */
@Service("paasCommentService")
@Slf4j
public class PaasCommentServiceImpl implements PaasCommentService {

    private static final Logger LOG = LoggerFactory.getLogger(PaasCommentServiceImpl.class);

    @Resource
    private UserService userService;
    @Resource
    private BaseProducer baseProducer;
    @Resource
    private PaasCommentModel paasCommentModel;
    @Resource
    private ProcessHelp processHelp;
    @Resource
    private SaasGetHelp saasGetHelp;
    @Resource
    private UserModel userModel;
    @Resource
    private CustomerStageLogModel customerStageLogModel;
    @Resource
    private LikeService likeService;
    @Resource
    private CabinetFileService cabinetFileService;
    @Resource
    private PaasProcessDataModel paasProcessDataModel;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private OpportunityStageLogModel opportunityStageLogModel;
    @Resource
    private PaasFormService paasFormService;
    @Resource
    private OpportunityModel opportunityModel;
    @Resource
    private CustomerModel customerModel;
    @Resource
    private ClueModel clueModel;
    @Resource
    private ClueStageLogModel clueStageLogModel;
    @Resource
    @Lazy
    private ScoreCalculateService scoreCalculateService;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private StageDetailHelp stageDetailHelp;
    @Resource
    private StageLogModel stageLogModel;
    @Resource
    private PaasProcessNodeTaskModel paasProcessNodeTaskModel;
    @Resource
    private LogThreadPoolBeanConfig logThreadPoolBeanConfig;
    @Resource
    private PaasProcessTaskModel paasProcessTaskModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private PaasFormDataModel paasFormDataModel;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private MessageService messageService;

    @Override
    public CommentListVO list(CommentListDTO commentListDTO) throws XbbException {
        CommentListVO commentListVO = new CommentListVO();
        try {
            Integer saasMark = commentListDTO.getSaasMark();
            BusinessCommentEnum businessCommentEnum;
            if(Objects.equals(saasMark,SaasMarkEnum.PAAS.getCode())){
                businessCommentEnum = BusinessCommentEnum.PAAS_STAGE;
            } else {
                businessCommentEnum = BusinessCommentEnum.getByBusinessType(commentListDTO.getBusinessType());
            }
            if (businessCommentEnum == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
            }
            Integer businessType = commentListDTO.getBusinessType();
            Long appId = commentListDTO.getAppId();
            String corpid = commentListDTO.getCorpid();
            //因为线索的跟进记录是存在客户这边的，所以在跟进记录这边评论的话，不能使用线索的appId,这边替换为crm的appId
            commentListDTO.setAppId(getAppId4Clue(corpid,businessType,appId));
            Long refId = commentListDTO.getRefId();
            //查库设了一下AppId,是因为前端没传吗,前端没传让前端补下好了,这段逻辑有点问题的
            /*if (Objects.nonNull(commentListDTO.getChildComments()) && !commentListDTO.getChildComments()) {
                PaasFormDataEntityExt paasFormDataEntityExt = saasGetHelp.getFormData(refId, corpid, commentListDTO.getBusinessType());
                if (Objects.nonNull(paasFormDataEntityExt)) {
                    appId = paasFormDataEntityExt.getAppId();
                    commentListDTO.setAppId(appId);
                }
            }*/
            Map<String, Object> map = BeanUtil.convertBean2Map(commentListDTO, true);
            map.put("type", businessCommentEnum.getCode());
            if (!commentListDTO.getChildComments()&&Objects.equals(businessCommentEnum,BusinessCommentEnum.WORK_ORDER)) {
                map.put("refUserIdIsNull", BasicConstant.ONE);
            }
            map.put("orderByStr", "add_time desc");
            List<PaasCommentEntityExt> list = paasCommentModel.list(map);
            if (list == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }

            List<Long> dataId = new ArrayList<>();
            dataId.add(-1L);
            list.forEach(paasCommentEntityExt -> {
                setSimpleUser(paasCommentEntityExt, commentListDTO);
                paasCommentEntityExt.setAddTimeStr(DateTimeUtil.getStringEpochSecond(paasCommentEntityExt.getAddTime(), DateTimeUtil.SDF));
                dataId.add(paasCommentEntityExt.getId());
            });
            Map<Long, Integer> likeCountMap = likeService.getLikeCountMap(dataId, commentListDTO.getCorpid(), businessCommentEnum.getCode());
            Map<Long, Integer> commentCountMap = paasCommentModel.getCommnetCountMap(dataId, commentListDTO.getCorpid(), businessCommentEnum.getCode());
            list.forEach(comment -> {
                comment.setCommentLikeCount(likeCountMap.getOrDefault(comment.getId(), BasicConstant.ZERO));
                comment.setCommentCountOfComment(commentCountMap.getOrDefault(comment.getId(), BasicConstant.ZERO));
            });
            // 设置评论下的回复数量
            eachSetReplyCount(corpid,list);
            setPermissionSet(list,commentListDTO,businessCommentEnum);
            commentListVO.setList(list);
            commentListVO.setCommentCount(list.size());
        } catch (Exception e) {
            LOG.error("paasFormData数据库查询数据出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return commentListVO;
    }

    private Long getAppId4Clue(String corpid,Integer businessType , Long appId){
        if(Objects.equals(XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode(),businessType) && Objects.nonNull(appId) && appId > 0){
            PaasAppEntity app = paasAppModel.getByKey(appId, corpid);
            if(Objects.nonNull(app) && XbbRefTypeEnum.MARKET_MANAGEMENT.getAlias().equals(app.getAlias())){
                PaasFormEntityExt customerCommunicateForm = paasFormModel.getByBusinessType(XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode(), corpid);
                if(Objects.nonNull(customerCommunicateForm)){
                   return  customerCommunicateForm.getAppId();
                }
            }
        }
        return appId;
    }
    private void setSimpleUser(PaasCommentEntityExt paasCommentEntityExt, BaseDTO baseDTO) {
        UserGetDTO userGetDTO = new UserGetDTO();
        BeanUtil.copyProperties(baseDTO, userGetDTO);
        userGetDTO.setTargetUserId(JSONArray.parseArray(paasCommentEntityExt.getAtUserId(), String.class));
        UserGetVO userGetVO;
        try {
            JSONArray jsonArray = new JSONArray();
            if ( CollectionsUtil.isNotEmpty(userGetDTO.getTargetUserId())) {
                userGetVO = userService.getUserInfoByTargetUserId(userGetDTO);
                userGetVO.getUserList().forEach(userVO -> {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("avatar", userVO.getAvatar());
                    jsonObject.put("id", String.valueOf(userVO.getUserId()));
                    jsonObject.put("name", userVO.getName());
                    jsonArray.add(jsonObject);
                });
            }
            paasCommentEntityExt.setAtUserIdList(jsonArray);
        } catch (XbbException e) {
            LOG.error("获取头像，姓名错误", e);
        }
    }

    private void setVisible(PaasCommentEntityExt paasCommentEntityExt, BaseDTO baseDTO, boolean hasSuperPermission, boolean hasNormalPermission) {
        JSONArray jsonArray = new JSONArray();
        if (hasSuperPermission || hasNormalPermission || ((baseDTO.getLoginUser().getUserId().equals(paasCommentEntityExt.getUserId()))
                && baseDTO.getLoginUser().getCorpid().equals(paasCommentEntityExt.getCorpid()))) {
            jsonArray.add("edit");
            jsonArray.add("delete");
        }
        paasCommentEntityExt.setPermissionSet(jsonArray);
    }


    @Override
    public CommentAddVO add(CommentAddDTO commentAddDTO) throws XbbException {
        CommentAddVO commentAddVO = new CommentAddVO();
        Integer saasMark = commentAddDTO.getSaasMark();
        try {
            Integer businessType = commentAddDTO.getBusinessType();
            BusinessCommentEnum businessCommentEnum;
            if(Objects.equals(saasMark,SaasMarkEnum.PAAS.getCode())){
                businessCommentEnum = BusinessCommentEnum.PAAS_STAGE;
            }else {
                businessCommentEnum = BusinessCommentEnum.getByBusinessType(commentAddDTO.getBusinessType());
            }
            if (businessCommentEnum == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
            }

            UserGetDTO userGetDTO = new UserGetDTO();
            BeanUtil.copyProperties(commentAddDTO, userGetDTO);
            List<String> targetUserId = new ArrayList<>();
            List<String> atUserIds = commentAddDTO.getAtUserIds();
            targetUserId.add(commentAddDTO.getUserId());
            Long appId = commentAddDTO.getAppId();
            String corpid = commentAddDTO.getCorpid();
            if (StringUtil.isNotEmpty(commentAddDTO.getRefUserId())) {
                targetUserId.add(commentAddDTO.getRefUserId());
            }
            userGetDTO.setTargetUserId(targetUserId);
            UserGetVO userGetVO = userService.getUserInfoByTargetUserId(userGetDTO);
            if (userGetVO == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
            }
            List<UserVO> userList = userGetVO.getUserList();
            Map<String, UserVO> userMap = new HashMap<>(userList.size());
            userList.forEach((item) -> userMap.put(item.getUserId(), item));

            PaasCommentEntity paasCommentEntity = new PaasCommentEntity();
            BeanUtils.copyProperties(commentAddDTO, paasCommentEntity);

            //因为线索的跟进记录是存在客户这边的，所以在跟进记录这边评论的话，不能使用线索的appId,这边替换为crm的appId
            paasCommentEntity.setAppId(getAppId4Clue(corpid,businessType,appId));
            UserVO userVO = userMap.get(commentAddDTO.getUserId());
            paasCommentEntity.setUserName(userVO.getName());
            paasCommentEntity.setUserAvatar(userVO.getAvatar());
            if (userMap.containsKey(commentAddDTO.getRefUserId())) {
                paasCommentEntity.setRefUserName(userMap.get(commentAddDTO.getRefUserId()).getName());
            }
            if (atUserIds == null) {
                atUserIds = new ArrayList<>();
            }
            paasCommentEntity.setAtUserId(JSON.toJSONString(atUserIds));
            atUserIds.remove(commentAddDTO.getRefUserId());
            paasCommentEntity.setRefId(commentAddDTO.getRefId());
            paasCommentEntity.setImage(JSONArray.toJSONString(commentAddDTO.getImages()));
            paasCommentEntity.setAttachment(JSONArray.toJSONString(commentAddDTO.getAttachmentList()));
            // 如果是回复型评论，设置parent_id和type
            if (commentAddDTO.isReply()) {
                paasCommentEntity.setType(BusinessCommentEnum.COMMENT_REPLY.getCode());
                paasCommentEntity.setReplyParentId(commentAddDTO.getReplyParentId() == null ? 0 : commentAddDTO.getReplyParentId());
            }else {
                paasCommentEntity.setType(businessCommentEnum.getCode());
            }
            paasCommentModel.insert(paasCommentEntity);

            // 如果是回复，重新设置refId，因为回复的refId是上级的评论id
            commentAddDTO.setRefId(getRefIdByIsReply(commentAddDTO.isReply(),commentAddDTO.getRefId(),corpid));

            //附件保存到文件柜
            switch (businessCommentEnum) {
                case APPROVAL:
                    businessType = XbbRefTypeEnum.APPROVAL.getCode();
                    break;
                case CONTRACT:
                    break;
                case OPPORTUNITY:
                    break;
                case CUSTOMER_COMMUNICATE:
                    break;
                case SUPPLIER_COMMUNICATE:
                    break;
                case WORK_REPORT:
                    break;
                case WORK_ORDER:
                    break;
                case CUSTOMER_STAGE:
                    businessType = XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode();
                    break;
                case SALE_STAGE:
                    businessType = XbbRefTypeEnum.SALES_OPPORTUNITY.getCode();
                    break;
                case CLUE_STAGE:
                    businessType = XbbRefTypeEnum.CLUE.getCode();
                    break;
                case CONTRACT_STAGE:
                    businessType = XbbRefTypeEnum.CONTRACT.getCode();
                    break;
                default:
                    break;
            }
            if (Objects.equals(businessCommentEnum, BusinessCommentEnum.CUSTOMER_STAGE) || Objects.equals(businessCommentEnum, BusinessCommentEnum.SALE_STAGE)
                    || Objects.equals(businessCommentEnum, BusinessCommentEnum.CLUE_STAGE) || Objects.equals(saasMark,SaasMarkEnum.PAAS.getCode())
                    || Objects.equals(businessCommentEnum, BusinessCommentEnum.CONTRACT_STAGE)) {
                //客户和机会阶段需要把附件放到文件柜里。businessType使用客户和机会的类型
                Long dataId = commentAddDTO.getDataId();
                List<PaasAttachmentEntityExt> attachmentList = commentAddDTO.getAttachmentList();
                if (Objects.nonNull(attachmentList) && attachmentList.size() > 0) {
                    CabinetFileSaveDTO cabinetFileSaveDTO = new CabinetFileSaveDTO(attachmentList, businessType, dataId);
                    cabinetFileSaveDTO.setUserId(commentAddDTO.getUserId());
                    cabinetFileSaveDTO.setCorpid(commentAddDTO.getCorpid());
                    cabinetFileSaveDTO.setLoginUserName(commentAddDTO.getLoginUserName());
                    cabinetFileSaveDTO.setHttpHeader(commentAddDTO.getHttpHeader());
                    cabinetFileSaveDTO.setType(CabinetFileTypeEnum.NORMAL.getType());
                    cabinetFileService.saveCabinetFiles(cabinetFileSaveDTO);
                }
                Long customerId = 0L;
                Long clueId = 0L;
                if (Objects.equals(businessCommentEnum, BusinessCommentEnum.SALE_STAGE) ) {
                    OpportunityEntityExt opportunityEntityExt = opportunityModel.getByKey(dataId,commentAddDTO.getCorpid());
                    customerId = FastJsonHelper.getLongOrDefaultFromFormData(opportunityEntityExt.getData(),SalesOpportunityEnum.CUSTOMER_NAME.getAttr(),0L);
                } else if (Objects.equals(businessCommentEnum, BusinessCommentEnum.CUSTOMER_STAGE)){
                    customerId = dataId;
                } else if (Objects.equals(businessCommentEnum, BusinessCommentEnum.CLUE_STAGE)){
                    clueId = dataId;
                }
                if(!Objects.equals(customerId,0L)){
                    //每填写一次阶段反馈时的创建时间影响最后跟进时间
                    Boolean flag = paasFormService.getSingleRuleList(commentAddDTO.getCorpid(), RuleSettingEnum.FILLING_IN_STAGE_FEEDBACK_CREATE_TIME.getConfig(), commentAddDTO.getFormId());
                    if ( flag ) {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put(CustomerManagementEnum.LAST_CONNECT_TIME.getAttr(), paasCommentEntity.getAddTime());
                        UpdateDataEntity updateData = ExplainUtil.getUpdateData(customerId, jsonObject, commentAddDTO.getCorpid());
                        customerModel.updateBatch(Collections.singletonList(updateData), commentAddDTO.getCorpid());
                        if (Objects.nonNull(updateData)) {
                            //评分更新（客户阶段，添加反馈（评论），修改了最后跟进时间）
                            scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT,commentAddDTO.getCorpid(),customerId,null);
                        }
                    }
                }
                if(!Objects.equals(clueId,0L)){
                    //每填写一次阶段反馈时的创建时间影响最后跟进时间
                    Boolean flag = proFormHelp.getClueSingleRuleList(commentAddDTO.getCorpid(), ClueRuleSettingEnum.FILLING_IN_STAGE_FEEDBACK_CREATE_TIME.getConfig(), commentAddDTO.getFormId());
                    if ( flag ) {
                        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        map.put(ClueEnum.LAST_CONNECT_TIME.getAttr(), paasCommentEntity.getAddTime());
                        clueModel.jsonsetNoSubById(commentAddDTO.getCorpid(), clueId, map);
                        //评分更新（线索阶段，添加反馈（评论），修改了最后跟进时间）
                        scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CLUE,commentAddDTO.getCorpid(),clueId,null);
                    }
                }

                stageDetailHelp.savaCommentLog( corpid,  saasMark,  businessType,  dataId,  commentAddDTO,  commentAddDTO.getRefId(),
                        "",commentAddDTO.getContent());
            }

            commentAddVO.setCommentId(paasCommentEntity.getId());
            // 评论/艾特消息推送
            pushComment(commentAddDTO.getLoginUser(), businessType, commentAddDTO.getRefId(), commentAddDTO.getCorpid(), atUserIds, CommentHelp.filterCommentContent(commentAddDTO.getContent()), businessCommentEnum, commentAddDTO.getIsInform());

            //老审批的评论日志记录
            if(Objects.equals(businessCommentEnum, BusinessCommentEnum.APPROVAL)){
                Runnable runnable = () -> {
                    try {
                        //日志
                        DetailLogPojo detailLogPojo = new DetailLogPojo();
                        detailLogPojo.setContentText(commentAddDTO.getContent());
                        detailLogPojo.setPictureCount(commentAddDTO.getImages().size());
                        detailLogPojo.setAttachmentCount(commentAddDTO.getAttachmentList().size());

                        PaasProcessTaskEntity processTaskEntity = paasProcessTaskModel.getByKey(commentAddDTO.getRefId().intValue(), corpid);
                        String creatorId = processTaskEntity.getCreatorId();
                        List<UserEntity> userEntityList = userModel.getByUserId(Collections.singletonList(creatorId), corpid);
                        PaasFormEntity paasFormEntityExt = proFormHelp.getPaasForm(processTaskEntity.getFormId(), processTaskEntity.getBusinessType(), corpid);
                        String title;
                        if (CollectionUtils.isEmpty(userEntityList)) {
                            title = "***"+ I18nMessageUtil.getMessage(CommonConstant.OF) + paasFormEntityExt.getName() + I18nMessageUtil.getMessage(I18nStringConstant.APPROVAL);
                        } else {
                            title = userEntityList.get(0).getName() + I18nMessageUtil.getMessage(CommonConstant.OF) + paasFormEntityExt.getName() + I18nMessageUtil.getMessage(I18nStringConstant.APPROVAL);
                        }
                        UserVO loginUser = commentAddDTO.getLoginUser();
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_WORKFLOW_COMMENT), loginUser.getName());
                        mongoLogHelp.buildLog4DetailArrWithComplexDetail(Collections.singletonList(detailLogPojo),commentAddDTO.getCorpid(),loginUser.getUserId(),loginUser.getName(), OperateModuleTypeEnum.APPROVAL, OperateTypeEnum.CREATE_APPROVE_COMMENT,null,title,memo,commentAddDTO.getHttpHeader(),BasicConstant.THREE);

                    }catch (XbbException e){
                        log.error("com.xbongbong.paas.service.impl.PaasCommentServiceImpl.add push or log: error");
                    }
                };
                logThreadPoolBeanConfig.sysLogThreadPool().execute(runnable);
            }

        } catch (Exception e) {
            LOG.error("paasFormData数据库查询数据出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return commentAddVO;
    }

    @Override
    public void pushComment(UserVO loginUser, Integer businessType, Long refId, String corpid, List<String> atUserIds, String content, BusinessCommentEnum businessCommentEnum, Boolean isInform) throws XbbException {
        PaasProcessDataEntity paasProcessDataEntity = null;
        if (Objects.isNull(businessCommentEnum)) {
            return;
        } else {
            if (Objects.equals(businessCommentEnum, BusinessCommentEnum.CUSTOMER_STAGE)) {
                businessType = XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode();
                CustomerStageLogEntity customerStageLogEntity = customerStageLogModel.getByKey(refId, corpid);
                if (Objects.isNull(customerStageLogEntity)) {
                    return;
                }
                refId = customerStageLogEntity.getDataId();
            } else if (Objects.equals(businessCommentEnum, BusinessCommentEnum.APPROVAL)) {
                paasProcessDataEntity = paasProcessDataModel.getByTaskId(refId, corpid);
                if (Objects.isNull(paasProcessDataEntity)){
                    return;
                }
                //isInform不为空且值为true表示勾选了,如果同时被@了，只发勾选的消息
                if (Objects.nonNull(isInform) && isInform) {
                    atUserIds.remove(paasProcessDataEntity.getCreatorId());
                }
                pushProcessComment(loginUser, refId, atUserIds);
                if (Objects.isNull(isInform) || !isInform) {
                    return;
                }
            } else if (Objects.equals(businessCommentEnum, BusinessCommentEnum.SALE_STAGE)) {
                OpportunityStageLogEntity opportunityStageLogEntity = opportunityStageLogModel.getByKey(refId, corpid);
                if (Objects.isNull(opportunityStageLogEntity)) {
                    return;
                }
                refId = opportunityStageLogEntity.getDataId();
                businessType = XbbRefTypeEnum.SALES_OPPORTUNITY.getCode();
            } else if (Objects.equals(businessCommentEnum, BusinessCommentEnum.CLUE_STAGE)) {
                ClueStageLogEntity clueStageLogEntity = clueStageLogModel.getByKey(refId, corpid);
                if (Objects.isNull(clueStageLogEntity)) {
                    return;
                }
                refId = clueStageLogEntity.getDataId();
                businessType = XbbRefTypeEnum.CLUE.getCode();
            } else if (Objects.equals(businessCommentEnum, BusinessCommentEnum.CONTRACT_STAGE)) {
                // 合同阶段是个Paas字段，相关的阶段记录存储的Paas的StageLog表
                StageLogEntity stageLogEntity = stageLogModel.getByKey(refId, corpid);
                if (Objects.isNull(stageLogEntity)) {
                    return;
                }
                refId = stageLogEntity.getDataId();
                businessType = XbbRefTypeEnum.CONTRACT.getCode();
            } else if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
                StageLogEntity stageLog = stageLogModel.getByKey(refId, corpid);
                if (Objects.isNull(stageLog)) {
                    return;
                }
                refId = stageLog.getDataId();
                businessType = XbbRefTypeEnum.PAAS.getCode();
            }
        }
        PaasFormDataEntityExt paasFormDataEntityExt = new PaasFormDataEntityExt();
        String creatorId;
        if (Objects.equals(businessCommentEnum, BusinessCommentEnum.APPROVAL)) {
            creatorId = paasProcessDataEntity.getCreatorId();
        } else {
            if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
                paasFormDataEntityExt = paasFormDataModel.getByKey(refId, corpid);
            } else {
                paasFormDataEntityExt = saasGetHelp.getFormData(refId, corpid, businessType);
            }
            if (Objects.isNull(paasFormDataEntityExt) ) {
                return;
            }
            creatorId = paasFormDataEntityExt.getCreatorId();
        }

        PaasFormEntityExt paasFormEntityExt = new PaasFormEntityExt();
        if (Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
            WorkOrderFormEntityExt workOrderFormEntity = workOrderFormModel.getByKey(paasFormDataEntityExt.getFormId(), corpid);
            BeanUtil.copyProperties(workOrderFormEntity, paasFormEntityExt);
        } else if (Objects.equals(businessCommentEnum, BusinessCommentEnum.APPROVAL)) {
            paasFormEntityExt = paasFormModel.getByKey(paasProcessDataEntity.getFormId(), corpid);
        } else {
            paasFormEntityExt = paasFormModel.getByKey(paasFormDataEntityExt.getFormId(), corpid);
        }
        // 后面需要用，就在拿出表单后加了
        TransmittableThreadLocalUtil.setValue(paasFormEntityExt.getSaasMark(), businessType, paasFormEntityExt.getMenuId(), paasFormEntityExt.getDistributorMark());
        if (Objects.equals(businessCommentEnum, BusinessCommentEnum.CUSTOMER_COMMUNICATE) && Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(), paasFormEntityExt.getDistributorMark())) {
            businessCommentEnum = BusinessCommentEnum.DISTRIBUTOR_COMMUNICATE;
        }

        String userName = loginUser.getName();
        String pushTitle = "";
        String pushContent = "";
        PushTypeEnum pushTypeEnum = null;
        switch (businessCommentEnum) {
            case CUSTOMER_COMMUNICATE:
                String customerName = FastJsonHelper.getStringOrDefaultFromFormData(paasFormDataEntityExt.getData(), CustomerCommunicateEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), "");
                pushTitle = I18nMessageUtil.getMessage(CommunicatePushConstant.COMMUNICATE_COMMENT_TITLE);
                pushContent = String.format(I18nMessageUtil.getMessage(CommunicatePushConstant.COMMUNICATE_COMMENT_CONTENT),
                        userName, customerName);
                Integer isClue = getIntegerOrDefaultFromFormData(paasFormDataEntityExt.getData(), CustomerCommunicateEnum.COMMUNICATE_BUSINESS_TYPE.getAttr(), 0);
                if (Objects.equals(isClue, XbbRefTypeEnum.CLUE.getCode())) {
                    customerName = FastJsonHelper.getStringOrDefaultFromFormData(paasFormDataEntityExt.getData(), CustomerCommunicateEnum.COMMUNICATE_BUSINESS_LINK_TEXT.getAttr(), "");
                    pushContent = String.format(I18nMessageUtil.getMessage(CommunicatePushConstant.COMMUNICATE_COMMENT_CONTENT_CLUE), userName,
                            customerName);
                }
                pushTypeEnum = PushTypeEnum.COMMUNICATE_COMMENT_PUSH;
                break;
            case DISTRIBUTOR_COMMUNICATE:
                String distributorName = FastJsonHelper.getStringOrDefaultFromFormData(paasFormDataEntityExt.getData(), DistributorCommunicateEnum.DISTRIBUTOR_NAME_LINK_TEXT.getAttr(), "");
                pushTitle = I18nMessageUtil.getMessage(DistributorCommunicatePushConstant.DISTRIBUTOR_COMMUNICATE_COMMENT_TITLE);
                pushContent = String.format(I18nMessageUtil.getMessage(DistributorCommunicatePushConstant.DISTRIBUTOR_COMMUNICATE_COMMENT_CONTENT),
                        userName, distributorName);
                pushTypeEnum = PushTypeEnum.DISTRIBUTOR_COMMUNICATE_COMMENT_PUSH;
                break;
            case SUPPLIER_COMMUNICATE:
                pushTitle = I18nMessageUtil.getMessage(CommunicatePushConstant.COMMUNICATE_COMMENT_TITLE);
                pushContent = String.format(I18nMessageUtil.getMessage(CommunicatePushConstant.SUPPLIER_COMMUNICATE_COMMENT_CONTENT),
                        userName, paasFormDataEntityExt.getData().getString(SupplierCommunicateEnum.SUPPLIER_NAME_LINK_TEXT.getAttr()));
                pushTypeEnum = PushTypeEnum.COMMUNICATE_COMMENT_PUSH;
                break;
            case WORK_REPORT:
                JSONObject workReportData = paasFormDataEntityExt.getData();
                Long reportDate = workReportData.getLong(WorkReportFieldEnum.REPORT_DATE.getAttr());
                Integer type = StringUtil.toInt(workReportData.getString(WorkReportFieldEnum.TYPE.getAttr()), WorkReportTypeEnum.DAILY.getType());
                WorkReportTypeEnum typeEnum = WorkReportTypeEnum.getByTypeWithDefault(type);
                switch (typeEnum) {
                    case DAILY:
                        String thisDay = DateTimeUtil.getStringEpochSecond(reportDate, DateTimeUtil.SDFDate);
                        pushContent = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_COMMENT_DAY_CONTENT), userName, thisDay);
                        break;
                    case WEEKLY:
                        String weekFirst = DateTimeUtil.getStringEpochSecond(DateTimeUtil.getWeekMorningInSomeday(reportDate), DateTimeUtil.SDFDate);
                        String weekLast = DateTimeUtil.getStringEpochSecond(DateTimeUtil.getWeekLastDayInSomeday(reportDate), DateTimeUtil.SDFDate);
                        pushContent = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_COMMENT_WEEK_CONTENT), userName, weekFirst, weekLast);
                        break;
                    case MONTHLY:
                        int month = StringUtil.toInt(DateTimeUtil.getMonth(reportDate));
                        String monthFirst = DateTimeUtil.getStringEpochSecond(DateTimeUtil.getFirstDateOfMonth(reportDate, month), DateTimeUtil.SDFDate);
                        String monthLast = DateTimeUtil.getStringEpochSecond(DateTimeUtil.getEndDateOfMonth(reportDate, month), DateTimeUtil.SDFDate);
                        pushContent = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_COMMENT_MONTH_CONTENT), userName, monthFirst, monthLast);
                        break;
                    default:
                        break;
                }
                pushTitle = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_COMMENT_TITLE), userName);
                pushTypeEnum = PushTypeEnum.WORK_REPORT_COMMENT_PUSH;
                break;
            case CUSTOMER_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(CustomerStagePushConstant.CUSTOMER_STAGE_COMMENT_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.CUSTOMER_STAGE;
                break;
            case WORK_ORDER:
                pushTitle = I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_COMMENT_TITLE);
                pushContent = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_DYNAMIC), userName, paasFormDataEntityExt.getSerialNo());
                pushTypeEnum = PushTypeEnum.WORKORDER_DYNAMIC_PUSH;
                break;
            case SALE_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(OpportunityStagePushConstant.OPPORTUNITY_STAGE_COMMENT_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.OPPORTUNITY_STAGE_PUSH;
                break;
            case CLUE_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(ClueStagePushConstant.CLUE_STAGE_COMMENT_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.CLUE_STAGE;
                break;
            case CONTRACT_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(ContractStagePushConstant.CONTRACT_STAGE_COMMENT_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.CONTRACT_STAGE_PUSH;
                break;
            case PAAS_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(PaasStagePushConstant.PAAS_STAGE_COMMENT_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.PAAS_STAGE;
                break;
            case APPROVAL:
                pushTitle = I18nMessageUtil.getMessage(ApprovalPushConstant.APPROVALPUSH_COMMENT_TITLE);
                UserEntity userEntity = userModel.getByKey(creatorId, paasProcessDataEntity.getCorpid());
                if (Objects.isNull(userEntity)) {
                    return;
                }
                String pushContentStr = userEntity.getName() + I18nMessageUtil.getMessage(CommonConstant.OF) + paasFormEntityExt.getName();
                pushContent = String.format(I18nMessageUtil.getMessage(ApprovalPushConstant.APPROVALPUSH_COMMENT), userName, pushContentStr);
                pushTypeEnum = PushTypeEnum.APPROVAL_PUSH_ADD_COMMENT;
                break;
            default:
                break;
        }
        if (!Objects.equals(loginUser.getUserId(), creatorId)) {
            List<String> pushUserList = Collections.singletonList(creatorId);
            PushRefTypePojo.Options options;
            if (Objects.equals(businessCommentEnum, BusinessCommentEnum.APPROVAL)) {
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("del", 0);
                param.put("corpid", corpid);
                param.put("taskId", paasProcessDataEntity.getTaskId());
                param.put("orderByStr", " id DESC ");
                List<PaasProcessNodeTaskEntityExt> nodeTaskList = paasProcessNodeTaskModel.findEntitys(param);
                if (nodeTaskList.isEmpty()) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_TASK_NOT_EXIST);
                }
                options = new PushRefTypePojo.Options(paasProcessDataEntity.getAppId(), paasProcessDataEntity.getMenuId(),
                        paasProcessDataEntity.getFormId(), Collections.singletonList(paasProcessDataEntity.getId()), paasProcessDataEntity.getSaasMark(), paasProcessDataEntity.getBusinessType(), refId, nodeTaskList.get(0).getId(), ProcessTypeEnum.CC.getValue());
            } else {
                Integer saasMark = SaasMarkEnum.SAAS.getCode();
                if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
                    saasMark = SaasMarkEnum.PAAS.getCode();
                }
                options = new PushRefTypePojo.Options(paasFormDataEntityExt.getAppId(), paasFormDataEntityExt.getMenuId(),
                        paasFormDataEntityExt.getFormId(), refId, Collections.singletonList(refId), saasMark, businessType, businessType, paasFormEntityExt.getDistributorMark());
                if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
                    PaasMenuEntity paasMenuEntity = paasMenuModel.getByKey(paasFormDataEntityExt.getMenuId(), corpid);
                    options.setName(Objects.nonNull(paasMenuEntity) ? paasMenuEntity.getName() : "");
                }
            }
            MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(refId), 0, null, pushTitle, pushContent, null, options);
            if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
                messageRabbitMqDTO.setPushTime(DateTimeUtil.getInt() + 10);
                messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, pushTypeEnum);
            } else {
                baseProducer.sendMessage(pushTypeEnum, messageRabbitMqDTO);
            }
        }

        atUserIds.remove(loginUser.getUserId());
        if (atUserIds.size() > 0 && !Objects.equals(businessCommentEnum, BusinessCommentEnum.APPROVAL)) {
            // 评论艾特消息推送
            pushCommentAt(loginUser, refId, corpid, atUserIds, businessCommentEnum, paasFormDataEntityExt, content);
        }
    }

    @Override
    public void pushCommentAt(UserVO loginUser, Long refId, String corpid, List<String> atUserIds, BusinessCommentEnum businessCommentEnum, PaasFormDataEntityExt paasFormDataEntityExt, String content) throws XbbException {
        Integer businessType = XbbRefTypeEnum.transferBusinessType2Index(businessCommentEnum.getBusinessType());
        UserEntity userEntity = userModel.getByKey(paasFormDataEntityExt.getCreatorId(), corpid);
        String creatorName = Objects.nonNull(userEntity) ? userEntity.getName() : "";
        String userName = loginUser.getName();
        String pushTitle = "";
        String pushContent = "";
        PushTypeEnum pushTypeEnum = null;
        switch (businessCommentEnum) {
            case CUSTOMER_COMMUNICATE:
                String customerName = FastJsonHelper.getStringOrDefaultFromFormData(paasFormDataEntityExt.getData(), CustomerCommunicateEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), "");
                pushTitle = I18nMessageUtil.getMessage(CommunicatePushConstant.COMMUNICATE_AT_TITLE);
                pushContent = String.format(I18nMessageUtil.getMessage(CommunicatePushConstant.COMMUNICATE_AT_CONTENT), userName,
                        customerName);
                Integer isClue = getIntegerOrDefaultFromFormData(paasFormDataEntityExt.getData(), CustomerCommunicateEnum.COMMUNICATE_BUSINESS_TYPE.getAttr(), 0);
                if (Objects.equals(isClue, XbbRefTypeEnum.CLUE.getCode())) {
                    customerName = FastJsonHelper.getStringOrDefaultFromFormData(paasFormDataEntityExt.getData(), CustomerCommunicateEnum.COMMUNICATE_BUSINESS_LINK_TEXT.getAttr(), "");
                    pushContent = String.format(I18nMessageUtil.getMessage(CommunicatePushConstant.COMMUNICATE_AT_CONTENT_CLUE), userName,
                            customerName);
                }
                pushTypeEnum = PushTypeEnum.COMMUNICATE_AT_PUSH;
                break;
            case DISTRIBUTOR_COMMUNICATE:
                String distributorName = FastJsonHelper.getStringOrDefaultFromFormData(paasFormDataEntityExt.getData(), DistributorCommunicateEnum.DISTRIBUTOR_NAME_LINK_TEXT.getAttr(), "");
                pushTitle = I18nMessageUtil.getMessage(DistributorCommunicatePushConstant.DISTRIBUTOR_COMMUNICATE_AT_TITLE);
                pushContent = String.format(I18nMessageUtil.getMessage(DistributorCommunicatePushConstant.DISTRIBUTOR_COMMUNICATE_AT_CONTENT), userName, distributorName);
                pushTypeEnum = PushTypeEnum.DISTRIBUTOR_COMMUNICATE_AT_PUSH;
                break;
            case SUPPLIER_COMMUNICATE:
                pushTitle = I18nMessageUtil.getMessage(CommunicatePushConstant.COMMUNICATE_AT_TITLE);
                pushContent = String.format(I18nMessageUtil.getMessage(CommunicatePushConstant.SUPPLIER_COMMUNICATE_AT_CONTENT), userName,
                        paasFormDataEntityExt.getData().getString(SupplierCommunicateEnum.SUPPLIER_NAME_LINK_TEXT.getAttr()));
                pushTypeEnum = PushTypeEnum.COMMUNICATE_AT_PUSH;
                break;
            case WORK_REPORT:
                JSONObject workReportData = paasFormDataEntityExt.getData();
                Long reportDate = workReportData.getLong(WorkReportFieldEnum.REPORT_DATE.getAttr());
                Integer type = StringUtil.toInt(workReportData.getString(WorkReportFieldEnum.TYPE.getAttr()), WorkReportTypeEnum.DAILY.getType());
                WorkReportTypeEnum typeEnum = WorkReportTypeEnum.getByTypeWithDefault(type);
                switch (typeEnum) {
                    case DAILY:
                        String thisDay = DateTimeUtil.getStringEpochSecond(reportDate, DateTimeUtil.SDFDate);
                        pushContent = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_AT_DAY_CONTENT), userName, creatorName, thisDay);
                        break;
                    case WEEKLY:
                        String weekFirst = DateTimeUtil.getStringEpochSecond(DateTimeUtil.getWeekMorningInSomeday(reportDate), DateTimeUtil.SDFDate);
                        String weekLast = DateTimeUtil.getStringEpochSecond(DateTimeUtil.getWeekLastDayInSomeday(reportDate), DateTimeUtil.SDFDate);
                        pushContent = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_AT_WEEK_CONTENT), userName, creatorName, weekFirst, weekLast);
                        break;
                    case MONTHLY:
                        int month = StringUtil.toInt(DateTimeUtil.getMonth(reportDate));
                        String monthFirst = DateTimeUtil.getStringEpochSecond(DateTimeUtil.getFirstDateOfMonth(reportDate, month), DateTimeUtil.SDFDate);
                        String monthLast = DateTimeUtil.getStringEpochSecond(DateTimeUtil.getEndDateOfMonth(reportDate, month), DateTimeUtil.SDFDate);
                        pushContent = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_AT_MONTH_CONTENT), userName, creatorName, monthFirst, monthLast);
                        break;
                    default:
                        break;
                }
                pushTitle = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_AT_TITLE), userName);
                pushTypeEnum = PushTypeEnum.WORK_REPORT_AT_PUSH;
                break;
            case CUSTOMER_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(CustomerStagePushConstant.CUSTOMER_STAGE_AT_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.CUSTOMER_STAGE;
                businessType = XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode();
                break;
            case WORK_ORDER:
                pushTitle = I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_COMMENT_AT_TITLE);
                pushContent = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_DYNAMIC_AT), userName, paasFormDataEntityExt.getSerialNo());
                pushTypeEnum = PushTypeEnum.WORKORDER_COMMENT_AT;
                break;
            case CONTRACT_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(ContractStagePushConstant.CONTRACT_STAGE_AT_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.CONTRACT_STAGE_PUSH;
                businessType = XbbRefTypeEnum.CONTRACT.getCode();
                break;
            case SALE_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(OpportunityStagePushConstant.OPPORTUNITY_STAGE_AT_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.OPPORTUNITY_STAGE_PUSH;
                businessType = XbbRefTypeEnum.SALES_OPPORTUNITY.getCode();
                break;
            case CLUE_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(ClueStagePushConstant.CLUE_STAGE_AT_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.CLUE_STAGE;
                businessType = XbbRefTypeEnum.CLUE.getCode();
                break;
            case PAAS_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(PaasStagePushConstant.PAAS_STAGE_AT_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.PAAS_STAGE;
                businessType = XbbRefTypeEnum.PAAS.getCode();
                break;
            default:
                break;
        }
        atUserIds.remove(loginUser.getUserId());
        DataPermissionParamsPojo dataPermissionParamsPojoValue = TransmittableThreadLocalUtil.getDataPermissionParamsPojoValue();
        Integer saasMark = SaasMarkEnum.SAAS.getCode();
        if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
            saasMark = SaasMarkEnum.PAAS.getCode();
        }
        PushRefTypePojo.Options options = new PushRefTypePojo.Options(paasFormDataEntityExt.getAppId(), paasFormDataEntityExt.getMenuId(), paasFormDataEntityExt.getFormId(), refId, Collections.singletonList(refId), saasMark, businessType, businessType, dataPermissionParamsPojoValue.getDistributorMark());
        if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
            PaasMenuEntity paasMenuEntity = paasMenuModel.getByKey(paasFormDataEntityExt.getMenuId(), corpid);
            options.setName(Objects.nonNull(paasMenuEntity) ? paasMenuEntity.getName() : "");
        }
        MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, atUserIds, Collections.singletonList(refId), 0, null, pushTitle, pushContent, null, options);
        if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
            messageRabbitMqDTO.setPushTime(DateTimeUtil.getInt() + 10);
            messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, pushTypeEnum);
        } else {
            baseProducer.sendMessage(pushTypeEnum, messageRabbitMqDTO);
        }
    }

    @Override
    public Integer getCount(String corpid, Integer businessType, Long appId, Long refId) {
        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("corpid", corpid);
        map.put("appId", appId);
        map.put("type", businessType);
        map.put("refId", refId);
        map.put("del", 0);
        return paasCommentModel.getEntitysCount(map);
    }

    @Override
    public Map<Long, Integer> getCommnetCountMap(List<Long> dataIdIn, String corpid, Integer code) {
        return paasCommentModel.getCommnetCountMap(dataIdIn, corpid, code);
    }

    @Override
    public Map<String, List<CommentPojo>> getStageComment(List<Long> stageLogIdIn, String corpid, Map<Long, String> codeMap, Integer type, BaseDTO baseDTO) throws XbbException{
        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("corpid", corpid);
        map.put("refIdIn", stageLogIdIn);
        map.put("type", type);
        map.put("del", 0);
        List<PaasCommentEntityExt> paasCommentEntityExtList = paasCommentModel.list(map);
        Map<String, List<CommentPojo>> commentMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasCommentEntityExt entityExt : paasCommentEntityExtList) {
            if (!codeMap.containsKey(entityExt.getRefId())) {
                continue;
            }
            String stageCode = codeMap.get(entityExt.getRefId());
            List<CommentPojo> commentPojoList = commentMap.getOrDefault(stageCode, new ArrayList<>());
            CommentPojo commentPojo = new CommentPojo();
            setSimpleUser(entityExt, baseDTO);
            BeanUtil.copyProperties(entityExt, commentPojo);
            commentPojo.setAddTimeStr(DateTimeUtil.getStringEpochSecond(entityExt.getAddTime()));
            commentPojoList.add(commentPojo);
            commentMap.put(stageCode, commentPojoList);
        }
        return commentMap;
    }

    @Override
    public List<Long> hasMyComment(List<Long> dataIdIn, String corpid, Integer type, String userId) {
        return paasCommentModel.hasMyComment(dataIdIn, corpid, type, userId);
    }

    @Override
    public List<PaasCommentEntityExt> getCommentDetail(CommentDetailDTO commentDetailDTO) throws XbbException {
        List<PaasCommentEntityExt> paasCommentEntityExts;
        try {
            BusinessCommentEnum businessCommentEnum = BusinessCommentEnum.getByBusinessType(commentDetailDTO.getBusinessType());
            if (businessCommentEnum == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", commentDetailDTO.getCorpid());
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("type", businessCommentEnum.getCode());
            param.put("idIn", commentDetailDTO.getDataId());
            paasCommentEntityExts = paasCommentModel.list(param);
            paasCommentEntityExts.forEach(paasCommentEntityExt -> {
                setSimpleUser(paasCommentEntityExt, commentDetailDTO);
            });
            setPermissionSet(paasCommentEntityExts,commentDetailDTO,businessCommentEnum);
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }

        return paasCommentEntityExts;
    }

    private void setPermissionSet( List<PaasCommentEntityExt> paasCommentEntityExts, BaseDTO baseDTO, BusinessCommentEnum businessCommentEnum){
        boolean isNormalManage;
        switch (businessCommentEnum) {
            case WORK_ORDER:
                isNormalManage = baseDTO.getLoginUser().isWorkOrderManager();
                break;
            case APPROVAL:
            case WORK_REPORT:
                isNormalManage = false;
                break;
            case CUSTOMER_COMMUNICATE:
            case CUSTOMER_STAGE:
            case SALE_STAGE:
            case CLUE_STAGE:
            case CONTRACT_STAGE:
                isNormalManage = baseDTO.getLoginUser().isManager();
                break;
            case SUPPLIER_COMMUNICATE:
                isNormalManage = baseDTO.getLoginUser().isPurchaseManager();
                break;
            default:
                isNormalManage = false;
                break;
        }
        paasCommentEntityExts.forEach(paasCommentEntityExt -> {
            boolean isWorkOrderManager = false;
            if(isNormalManage) {
                UserEntity userEntity = new UserEntity();
                BeanUtil.copyProperties(baseDTO.getLoginUser(), userEntity);
                Integer dataPermission = userModel.getDataPermission(userEntity, true);
                List<String> userIdList = userModel.getSubIdListByDataPermission(dataPermission, userEntity.getUserId(), userEntity.getCorpid(), BasicConstant.ONE, false);
                if (!userIdList.isEmpty()) {
                    isWorkOrderManager = userIdList.contains(paasCommentEntityExt.getUserId());
                }
            }
            setVisible(paasCommentEntityExt, baseDTO, baseDTO.getLoginUser().isAdminOrBoss(),isWorkOrderManager);
        });
    }

    @Override
    public CommentAddOnCommentVO addOnComment(CommentAddOnCommentDTO commentAddOnCommentDTO) throws XbbException {
        CommentAddOnCommentVO commentAddOnCommentVO = new CommentAddOnCommentVO();
        try {
            Integer businessType = commentAddOnCommentDTO.getBusinessType();
            String corpid = commentAddOnCommentDTO.getCorpid();
            BusinessCommentEnum businessCommentEnum = BusinessCommentEnum.getByBusinessType(businessType);
            if (Objects.isNull(businessCommentEnum)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
            }

            UserGetDTO userGetDTO = new UserGetDTO();
            BeanUtil.copyProperties(commentAddOnCommentDTO, userGetDTO);
            List<String> targetUserId = new ArrayList<>();
            List<String> atUserIds = commentAddOnCommentDTO.getAtUserIds();
            targetUserId.add(commentAddOnCommentDTO.getUserId());
            if (StringUtil.isNotEmpty(commentAddOnCommentDTO.getRefUserId())) {
                targetUserId.add(commentAddOnCommentDTO.getRefUserId());
            }
            if (atUserIds != null && !atUserIds.isEmpty()) {
                targetUserId.addAll(commentAddOnCommentDTO.getAtUserIds());
            }
            userGetDTO.setTargetUserId(targetUserId);
            UserGetVO userGetVO = userService.getUserInfoByTargetUserId(userGetDTO);
            if (userGetVO == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.USER_NOT_EXIST);
            }
            List<UserVO> userList = userGetVO.getUserList();
            Map<String, UserVO> userMap = new HashMap<>(userList.size());
            userList.forEach((item) -> userMap.put(item.getUserId(), item));

            PaasCommentEntity paasCommentEntity = new PaasCommentEntity();
            BeanUtils.copyProperties(commentAddOnCommentDTO, paasCommentEntity);
            UserVO userVO = userMap.get(commentAddOnCommentDTO.getUserId());
            paasCommentEntity.setType(businessCommentEnum.getCode());
            paasCommentEntity.setUserName(userVO.getName());
            paasCommentEntity.setUserAvatar(userVO.getAvatar());
            if (userMap.containsKey(commentAddOnCommentDTO.getRefUserId())) {
                paasCommentEntity.setRefUserName(userMap.get(commentAddOnCommentDTO.getRefUserId()).getName());
            }
            if (atUserIds == null) {
                atUserIds = new ArrayList<>();
            }
            atUserIds.remove(commentAddOnCommentDTO.getRefUserId());
            paasCommentEntity.setAtUserId(JSON.toJSONString(atUserIds));
            paasCommentEntity.setRefId(commentAddOnCommentDTO.getRefId());
            paasCommentEntity.setImage(JSONArray.toJSONString(commentAddOnCommentDTO.getImages()));
            paasCommentEntity.setAttachment(JSONArray.toJSONString(commentAddOnCommentDTO.getAttachmentList()));
            paasCommentModel.insert(paasCommentEntity);

            commentAddOnCommentVO.setCommentId(paasCommentEntity.getId());

            //消息推送,评论评论消息
            Long dataId = 0L;
            String creatorId = "";
//            if (Objects.equals(commentAddOnCommentDTO.getFatherComment(), 0)) {
            //评论的那条评论
            PaasCommentEntity commentEntity = paasCommentModel.getByKey(commentAddOnCommentDTO.getRefId(), corpid);
            if (Objects.isNull(commentEntity)) {
                return commentAddOnCommentVO;
            }
            dataId = commentEntity.getRefId();
            creatorId = commentEntity.getUserId();
//            } else {
//                //评论的那条评论
//                PaasCommentEntity commentEntity = paasCommentModel.getByKey(commentAddOnCommentDTO.getRefId(), corpid);
//                if (Objects.isNull(commentEntity)) {
//                    return commentAddOnCommentVO;
//                }
//                PaasCommentEntity fatherComment = paasCommentModel.getByKey(commentEntity.getRefId(), corpid);
//                if (Objects.isNull(fatherComment)) {
//                    return commentAddOnCommentVO;
//                }
//                dataId = fatherComment.getRefId();
//                creatorId = commentEntity.getUserId();
//            }

            PaasFormDataEntityExt paasFormDataEntityExt = saasGetHelp.getFormData(dataId, corpid, businessType);
            if (Objects.isNull(paasFormDataEntityExt)) {
                return commentAddOnCommentVO;
            }

            UserVO loginUser = commentAddOnCommentDTO.getLoginUser();
            String userName = loginUser.getName();
            String pushTitle = "";
            String pushContent = "";
            PushTypeEnum pushTypeEnum = null;
            PushRefTypePojo.Options options;
            MessageRabbitMqDTO messageRabbitMqDTO;
            if (!Objects.equals(loginUser.getUserId(), creatorId)) {
                switch (businessCommentEnum) {
                    case WORK_ORDER:
                        pushTitle = I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_COMMENT_TITLE);
                        pushContent = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_COMMENT), userName, paasFormDataEntityExt.getSerialNo());
                        pushTypeEnum = PushTypeEnum.WORKORDER_COMMENT_PUSH;
                        break;
                    default:
                        break;
                }
                List<String> pushUserList = Collections.singletonList(creatorId);
                options = new PushRefTypePojo.Options(paasFormDataEntityExt.getAppId(), paasFormDataEntityExt.getMenuId(), paasFormDataEntityExt.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), businessType, businessType);
                messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(dataId), 0, null, pushTitle, pushContent, null, options);
                baseProducer.sendMessage(pushTypeEnum, messageRabbitMqDTO);
            }

            if (atUserIds.size() > 0) {
                //@消息推送
                switch (businessCommentEnum) {
                    case WORK_ORDER:
                        pushTitle = I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_COMMENT_AT_TITLE);
                        pushContent = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_DYNAMIC_AT), userName, paasFormDataEntityExt.getSerialNo());
                        pushTypeEnum = PushTypeEnum.WORKORDER_COMMENT_AT;
                        break;
                    default:
                        break;
                }
                atUserIds.remove(loginUser.getUserId());
                options = new PushRefTypePojo.Options(paasFormDataEntityExt.getAppId(), paasFormDataEntityExt.getMenuId(), paasFormDataEntityExt.getFormId(), dataId, Collections.singletonList(dataId), SaasMarkEnum.SAAS.getCode(), businessType, businessType);
                messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, atUserIds, Collections.singletonList(dataId), 0, null, pushTitle, pushContent, null, options);
                baseProducer.sendMessage(pushTypeEnum, messageRabbitMqDTO);
            }

            //记录日志


        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("PaasCommentServiceImpl.addOnComment 出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return commentAddOnCommentVO;
    }

    @Override
    public void pushProcessComment(UserVO loginUser, Long refId, List<String> atUserIds) throws XbbException {
        processHelp.pushProcessComment(loginUser, refId, atUserIds);
    }

    @Override
    public CommentDeleteVO delete(CommentDeleteDTO commentDeleteDTO) throws XbbException {
        CommentDeleteVO commentDeleteVO = new CommentDeleteVO();
        try {
            Integer businessType = commentDeleteDTO.getBusinessType();
            Integer saasMark = commentDeleteDTO.getSaasMark();
            BusinessCommentEnum businessCommentEnum = BusinessCommentEnum.getByBusinessType(businessType);
            if (businessCommentEnum == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
            }
            PaasCommentEntity paasCommentEntity = paasCommentModel.getByKey(commentDeleteDTO.getCommentId(), commentDeleteDTO.getCorpid());
            if (paasCommentEntity == null) {
                return commentDeleteVO;
            }

            // 阶段推进器下的评论和回复删除走特殊逻辑，目前只有阶段推进器的回复有层级关系 end-time 2023-03-02
            if (BusinessCommentEnum.isStage(businessType) && commentDeleteDTO.isReply()) {
                paasCommentModel.deleteByKey(paasCommentEntity.getId(),paasCommentEntity.getCorpid());
            } else if (BusinessCommentEnum.isStage(businessType) && !commentDeleteDTO.isReply()){
                paasCommentModel.deleteCommentWithReply(paasCommentEntity.getId(), paasCommentEntity.getCorpid(), BusinessCommentEnum.COMMENT_REPLY.getCode(),paasCommentEntity.getAppId());
            }else {
                paasCommentModel.deleteByKey(commentDeleteDTO.getCommentId(), commentDeleteDTO.getCorpid());
                paasCommentModel.deleteByRefId(paasCommentEntity.getId(),paasCommentEntity.getCorpid(),paasCommentEntity.getAppId(),paasCommentEntity.getType());
            }

            // 如果是回复，重新设置refId，因为回复的refId是上级的评论id
            commentDeleteDTO.setRefId(getRefIdByIsReply(commentDeleteDTO.isReply(),commentDeleteDTO.getRefId(),commentDeleteDTO.getCorpid()));

            switch (businessCommentEnum) {
                case CUSTOMER_STAGE:
                    businessType = XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode();
                    break;
                case SALE_STAGE:
                    businessType = XbbRefTypeEnum.SALES_OPPORTUNITY.getCode();
                    break;
                case CLUE_STAGE:
                    businessType = XbbRefTypeEnum.CLUE.getCode();
                    break;
                case CONTRACT_STAGE:
                    businessType = XbbRefTypeEnum.CONTRACT.getCode();
                    break;
                case PAAS_STAGE:
                    businessType = XbbRefTypeEnum.PAAS.getCode();
                    saasMark = SaasMarkEnum.PAAS.getCode();
                    break;
                default:
                    break;
            }

            Long refId = commentDeleteDTO.getRefId();
            boolean isStage = false;
            if ( Objects.equals(businessCommentEnum, BusinessCommentEnum.CUSTOMER_STAGE)   ) {
                CustomerStageLogEntity customerStageLogEntity = customerStageLogModel.getByKey(refId,commentDeleteDTO.getCorpid());
                refId = customerStageLogEntity.getDataId();
                isStage = true;
            }else if ( Objects.equals(businessCommentEnum, BusinessCommentEnum.SALE_STAGE) ){
                OpportunityStageLogEntity opportunityStageLogEntity = opportunityStageLogModel.getByKey(refId,commentDeleteDTO.getCorpid());
                refId = opportunityStageLogEntity.getDataId();
                isStage = true;
            }else if ( Objects.equals(businessCommentEnum, BusinessCommentEnum.CLUE_STAGE) ){
                ClueStageLogEntity clueStageLogEntity = clueStageLogModel.getByKey(refId,commentDeleteDTO.getCorpid());
                refId = clueStageLogEntity.getDataId();
                isStage = true;
            } else if (Objects.equals(businessCommentEnum, BusinessCommentEnum.CONTRACT_STAGE)){
                // 合同阶段是个Paas字段，相关的阶段记录存储的Paas的StageLog表
                StageLogEntity stageLogEntity = stageLogModel.getByKey(refId, commentDeleteDTO.getCorpid());
                refId = stageLogEntity.getDataId();
                isStage = true;
            }else if ( Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE) ){
                StageLogEntity stageLogEntity = stageLogModel.getByKey(refId,commentDeleteDTO.getCorpid());
                refId = stageLogEntity.getDataId();
                isStage = true;
            }

            if(isStage){
                stageDetailHelp.savaCommentLog( commentDeleteDTO.getCorpid(),  saasMark,  businessType,  refId,  commentDeleteDTO,  commentDeleteDTO.getRefId(),
                        paasCommentEntity.getContent(),"");
            }
            commentDeleteVO.setCommentId(commentDeleteDTO.getCommentId());
            // 评论删除消息推送
            pushCommentDelete(commentDeleteDTO.getLoginUser(), businessType, commentDeleteDTO.getSubType(), refId, commentDeleteDTO.getCorpid(), CommentHelp.filterCommentContent(paasCommentEntity.getContent()), businessCommentEnum);

            //老审批的评论要记录日志
            if(Objects.equals(businessCommentEnum, BusinessCommentEnum.APPROVAL)){
                Runnable runnable = () -> {
                    try{
                        JSONArray imageArray = JSONArray.parseArray(paasCommentEntity.getImage());
                        int pictureCount = Objects.nonNull(imageArray) ? imageArray.size() : 0;
                        JSONArray attachmentArray = JSONArray.parseArray(paasCommentEntity.getAttachment());
                        int attachmentCount = Objects.nonNull(attachmentArray) ? attachmentArray.size() : 0;
                        String corpid = commentDeleteDTO.getCorpid();
                        //操作日志
                        DetailLogPojo detailLogPojo = new DetailLogPojo();
                        detailLogPojo.setContentText(paasCommentEntity.getContent());
                        detailLogPojo.setPictureCount(pictureCount);
                        detailLogPojo.setAttachmentCount(attachmentCount);
                        PaasProcessTaskEntity processTaskEntity = paasProcessTaskModel.getByKey(commentDeleteDTO.getRefId().intValue(), corpid);
                        String creatorId = processTaskEntity.getCreatorId();
                        List<UserEntity> userEntityList = userModel.getByUserId(Collections.singletonList(creatorId), corpid);
                        PaasFormEntity paasFormEntityExt = proFormHelp.getPaasForm(processTaskEntity.getFormId(), processTaskEntity.getBusinessType(), corpid);
                        String title;
                        if (CollectionUtils.isEmpty(userEntityList)) {
                            title = "***"+ I18nMessageUtil.getMessage(CommonConstant.OF) + paasFormEntityExt.getName() + I18nMessageUtil.getMessage(I18nStringConstant.APPROVAL);
                        } else {
                            title = userEntityList.get(0).getName() + I18nMessageUtil.getMessage(CommonConstant.OF) + paasFormEntityExt.getName() + I18nMessageUtil.getMessage(I18nStringConstant.APPROVAL);
                        }
                        UserVO loginUser = commentDeleteDTO.getLoginUser();
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DEL_WORKFLOW_COMMENT), loginUser.getName());
                        mongoLogHelp.buildLog4DetailArrWithComplexDetail(Collections.singletonList(detailLogPojo),corpid,loginUser.getUserId(),loginUser.getName(), OperateModuleTypeEnum.APPROVAL, OperateTypeEnum.DEL_APPROVE_COMMENT,null,title,memo,commentDeleteDTO.getHttpHeader(),BasicConstant.THREE);

                    }catch (XbbException e){
                        log.error("com.xbongbong.paas.service.impl.PaasCommentServiceImpl.delete push or log: error");
                    }
                };
                logThreadPoolBeanConfig.sysLogThreadPool().execute(runnable);
            }

        } catch (Exception e) {
            LOG.error("paasFormData数据库查询数据出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return commentDeleteVO;
    }

    @Override
    public void pushCommentDelete(UserVO loginUser, Integer businessType, Integer subType, Long refId, String corpid, String content, BusinessCommentEnum businessCommentEnum) throws XbbException {
        if (Objects.isNull(businessCommentEnum)) {
            return;
        }
        String userName = loginUser.getName();
        String pushTitle = "";
        String pushContent = "";
        PushTypeEnum pushTypeEnum = null;
        String creatorId = null;
        Long appId = 0L;
        Long menuId = 0L;
        Long formId = 0L;
        PaasFormDataEntityExt paasFormDataEntityExt;
        if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
            paasFormDataEntityExt = paasFormDataModel.getByKey(refId, corpid);
        } else {
            paasFormDataEntityExt = saasGetHelp.getFormData(refId, corpid, businessType);
        }
        if (Objects.nonNull(paasFormDataEntityExt) && !Objects.equals(businessCommentEnum,BusinessCommentEnum.APPROVAL)) {
             creatorId = paasFormDataEntityExt.getCreatorId();
             appId = paasFormDataEntityExt.getAppId();
             menuId = paasFormDataEntityExt.getMenuId();
             formId = paasFormDataEntityExt.getFormId();
        } else if ( Objects.isNull(paasFormDataEntityExt) && !Objects.equals(businessCommentEnum,BusinessCommentEnum.APPROVAL)){
            return;
        }

        PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(formId, corpid);
        if (paasFormEntityExt == null) {
            return;
        }

        if (Objects.equals(businessCommentEnum, BusinessCommentEnum.CUSTOMER_COMMUNICATE) && Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(), paasFormEntityExt.getDistributorMark())) {
            businessCommentEnum = BusinessCommentEnum.DISTRIBUTOR_COMMUNICATE;
        }

        if (subType != null && subType == 1) {
            switch (businessCommentEnum) {
                case APPROVAL:
                    PaasProcessDataEntity paasProcessDataEntity = paasProcessDataModel.getByTaskId(refId, corpid);
                    if (paasProcessDataEntity == null) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_TASK_NOT_EXIST);
                    }
                    creatorId = paasProcessDataEntity.getCreatorId();
                    appId = paasProcessDataEntity.getAppId();
                    menuId = paasProcessDataEntity.getMenuId();
                    formId = paasProcessDataEntity.getFormId();
                    Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    param.put("corpid", loginUser.getCorpid());
                    param.put("del", 0);
                    param.put("userId", creatorId);
                    List<UserEntity> userList = userModel.findEntitys(param);
                    pushTitle = I18nMessageUtil.getMessage(ProcessPushConstant.PROCESS_COMMENT_TITLE);
                    pushContent = String.format(I18nMessageUtil.getMessage(ProcessPushConstant.PROCESS_COMMENT_DEL_CONTENT), userName, userList.isEmpty() ? "" : userList.get(0).getName());
                    pushTypeEnum = PushTypeEnum.APPROVAL_COMMENT_DEL;

                    if (!Objects.equals(loginUser.getUserId(), creatorId)) {
                        List<String> pushUserList = Collections.singletonList(creatorId);
                        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        params.put("del", 0);
                        params.put("corpid", corpid);
                        params.put("taskId", paasProcessDataEntity.getTaskId());
                        param.put("nodeType", NodeTypeEnum.START_PROCESS_NODE.getNodeType());
                        params.put("orderByStr", " id DESC ");
                        List<PaasProcessNodeTaskEntityExt> nodeTaskList = paasProcessNodeTaskModel.findEntitys(params);
                        if (nodeTaskList.isEmpty()) {
                            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_TASK_NOT_EXIST);
                        }
                        PushRefTypePojo.Options options = new PushRefTypePojo.Options(appId, menuId, formId, Collections.singletonList(refId), paasProcessDataEntity.getSaasMark(), paasProcessDataEntity.getBusinessType(), refId, nodeTaskList.get(0).getId(), ProcessTypeEnum.TODO.getValue());
                        MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(refId), 0, null, pushTitle, pushContent, null, options);
                        baseProducer.sendMessage(pushTypeEnum, messageRabbitMqDTO);
                    }
                    return;
                case CUSTOMER_COMMUNICATE:
                case SUPPLIER_COMMUNICATE:
                    pushTitle = I18nMessageUtil.getMessage(CommunicatePushConstant.COMMUNICATE_COMMENT_DEL_TITLE);
                    String name = FastJsonHelper.getStringOrDefaultFromFormData(paasFormDataEntityExt.getData(), CustomerCommunicateEnum.CUSTOMER_NAME_LINK_TEXT.getAttr(), "");
                    pushContent = String.format(I18nMessageUtil.getMessage(CommunicatePushConstant.COMMUNICATE_COMMENT_DEL_CONTENT), userName, name);

                    Integer isClue = getIntegerOrDefaultFromFormData(paasFormDataEntityExt.getData(), CustomerCommunicateEnum.COMMUNICATE_BUSINESS_TYPE.getAttr(), 0);
                    if (Objects.equals(isClue, XbbRefTypeEnum.CLUE.getCode())) {
                        name = FastJsonHelper.getStringOrDefaultFromFormData(paasFormDataEntityExt.getData(), CustomerCommunicateEnum.COMMUNICATE_BUSINESS_LINK_TEXT.getAttr(), "");
                        pushContent = String.format(I18nMessageUtil.getMessage(CommunicatePushConstant.COMMUNICATE_COMMENT_DEL_CONTENT_CLUE), userName,
                                name);
                    }

                    pushTypeEnum = PushTypeEnum.COMMUNICATE_COMMENT_DEL_PUSH;
                    break;
                case DISTRIBUTOR_COMMUNICATE:
                    String distributorName = FastJsonHelper.getStringOrDefaultFromFormData(paasFormDataEntityExt.getData(), DistributorCommunicateEnum.DISTRIBUTOR_NAME_LINK_TEXT.getAttr(), "");
                    pushTitle = I18nMessageUtil.getMessage(DistributorCommunicatePushConstant.DISTRIBUTOR_COMMUNICATE_COMMENT_DEL_TITLE);
                    pushContent = String.format(I18nMessageUtil.getMessage(DistributorCommunicatePushConstant.DISTRIBUTOR_COMMUNICATE_COMMENT_DEL_CONTENT), userName, distributorName);
                    pushTypeEnum = PushTypeEnum.DISTRIBUTOR_COMMUNICATE_COMMENT_DEL_PUSH;
                    break;
                case WORK_REPORT:
                    JSONObject workReportData = paasFormDataEntityExt.getData();
                    Long reportDate = workReportData.getLong(WorkReportFieldEnum.REPORT_DATE.getAttr());
                    Integer type = StringUtil.toInt(workReportData.getString(WorkReportFieldEnum.TYPE.getAttr()), WorkReportTypeEnum.DAILY.getType());
                    WorkReportTypeEnum typeEnum = WorkReportTypeEnum.getByTypeWithDefault(type);
                    switch (typeEnum) {
                        case DAILY:
                            String thisDay = DateTimeUtil.getStringEpochSecond(reportDate, DateTimeUtil.SDFDate);
                            pushContent = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_COMMENT_DAY_DEL_CONTENT), userName, thisDay);
                            break;
                        case WEEKLY:
                            String weekFirst = DateTimeUtil.getStringEpochSecond(DateTimeUtil.getWeekMorningInSomeday(reportDate), DateTimeUtil.SDFDate);
                            String weekLast = DateTimeUtil.getStringEpochSecond(DateTimeUtil.getWeekLastDayInSomeday(reportDate), DateTimeUtil.SDFDate);
                            pushContent = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_COMMENT_WEEK_DEL_CONTENT), userName, weekFirst, weekLast);
                            break;
                        case MONTHLY:
                            int month = StringUtil.toInt(DateTimeUtil.getMonth(reportDate));
                            String monthFirst = DateTimeUtil.getStringEpochSecond(DateTimeUtil.getFirstDateOfMonth(reportDate, month), DateTimeUtil.SDFDate);
                            String monthLast = DateTimeUtil.getStringEpochSecond(DateTimeUtil.getEndDateOfMonth(reportDate, month), DateTimeUtil.SDFDate);
                            pushContent = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_COMMENT_MONTH_DEL_CONTENT), userName, monthFirst, monthLast);
                            break;
                        default:
                            break;
                    }
                    pushTitle = String.format(I18nMessageUtil.getMessage(WorkReportPushConstant.WORK_REPORT_COMMENT_DEL_TITLE), userName);
                    pushTypeEnum = PushTypeEnum.WORK_REPORT_COMMENT_DEL_PUSH;
                    break;
                case WORK_ORDER:
                    PaasCommentEntity paasCommentEntity = paasCommentModel.getByKey(refId, corpid);
                    pushTitle = I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_COMMENT_TITLE);
                    pushContent = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_COMMENT_DEL), loginUser.getName(), paasFormDataEntityExt.getSerialNo());
                    pushTypeEnum = PushTypeEnum.WORKORDER_COMMENT_DEL_PUSH;
                    creatorId = paasCommentEntity.getUserId();
                    refId = paasCommentEntity.getRefId();
                    break;
                default:
                    break;
            }
        } else if (subType == null || subType == 0) {
            switch (businessCommentEnum) {
                case WORK_ORDER:
                    pushTitle = I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_COMMENT_TITLE);
                    pushContent = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_DYNAMIC_DEL), userName, paasFormDataEntityExt.getSerialNo());
                    pushTypeEnum = PushTypeEnum.WORKORDER_DYNAMIC_DEL_PUSH;
                    break;
                case CONTRACT_STAGE:
                    pushTitle = String.format(I18nMessageUtil.getMessage(ContractStagePushConstant.CONTRACT_STAGE_COMMENT_DEL_TITLE), userName);
                    pushContent = content;
                    pushTypeEnum = PushTypeEnum.CONTRACT_STAGE_PUSH;
                    break;
                case CUSTOMER_STAGE:
                    pushTitle = String.format(I18nMessageUtil.getMessage(CustomerStagePushConstant.CUSTOMER_STAGE_COMMENT_DEL_TITLE), userName);
                    pushContent = content;
                    pushTypeEnum = PushTypeEnum.CUSTOMER_STAGE;
                    break;
                case SALE_STAGE:
                    pushTitle = String.format(I18nMessageUtil.getMessage(OpportunityStagePushConstant.OPPORTUNITY_STAGE_COMMENT_DEL_TITLE), userName);
                    pushContent = content;
                    pushTypeEnum = PushTypeEnum.OPPORTUNITY_STAGE_PUSH;
                    break;
                case CLUE_STAGE:
                    pushTitle = String.format(I18nMessageUtil.getMessage(ClueStagePushConstant.CLUE_STAGE_COMMENT_DEL_TITLE), userName);
                    pushContent = content;
                    pushTypeEnum = PushTypeEnum.CLUE_STAGE;
                    break;
                case PAAS_STAGE:
                    pushTitle = String.format(I18nMessageUtil.getMessage(PaasStagePushConstant.PAAS_STAGE_COMMENT_DEL_TITLE), userName);
                    pushContent = content;
                    pushTypeEnum = PushTypeEnum.PAAS_STAGE;
                    break;
            }
        }
        if (!Objects.equals(loginUser.getUserId(), creatorId)) {
            List<String> pushUserList = Collections.singletonList(creatorId);
            Integer saasMark = SaasMarkEnum.SAAS.getCode();
            if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
                saasMark = SaasMarkEnum.PAAS.getCode();
            }
            PushRefTypePojo.Options options = new PushRefTypePojo.Options(appId, menuId, formId, refId, Collections.singletonList(refId), saasMark, businessType, businessType, paasFormEntityExt.getDistributorMark());
            if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
                PaasMenuEntity paasMenuEntity = paasMenuModel.getByKey(menuId, corpid);
                options.setName(Objects.nonNull(paasMenuEntity) ? paasMenuEntity.getName() : "");
            }
            MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(refId), 0, null, pushTitle, pushContent, null, options);
            if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
                messageRabbitMqDTO.setPushTime(DateTimeUtil.getInt() + 10);
                messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, pushTypeEnum);
            } else {
                baseProducer.sendMessage(pushTypeEnum, messageRabbitMqDTO);
            }
        }
    }

    @Override
    public CommentAddVO edit(CommentEditDTO commentEditDTO) throws XbbException {
        CommentAddVO commentAddVO = new CommentAddVO();
        try {
            Integer businessType = commentEditDTO.getBusinessType();
            Integer saasMark = commentEditDTO.getSaasMark();
            BusinessCommentEnum businessCommentEnum = null;
            if(Objects.equals(saasMark,SaasMarkEnum.PAAS.getCode()) || Objects.equals(businessType, XbbRefTypeEnum.PAAS.getCode())){
                businessCommentEnum = BusinessCommentEnum.PAAS_STAGE;
            }else {
                businessCommentEnum = BusinessCommentEnum.getByBusinessType(commentEditDTO.getBusinessType());
            }

            if (businessCommentEnum == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
            }
            //附件保存到文件柜
            switch (businessCommentEnum) {
                case CUSTOMER_STAGE:
                    businessType = XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode();
                    break;
                case SALE_STAGE:
                    businessType = XbbRefTypeEnum.SALES_OPPORTUNITY.getCode();
                    break;
                case CLUE_STAGE:
                    businessType = XbbRefTypeEnum.CLUE.getCode();
                    break;
                case PAAS_STAGE:
                    businessType = XbbRefTypeEnum.PAAS.getCode();
                    saasMark = SaasMarkEnum.PAAS.getCode();
                    break;
                case CONTRACT_STAGE:
                    businessType = XbbRefTypeEnum.CONTRACT.getCode();
                    break;
                default:
                    break;
            }
            PaasCommentEntity paasCommentEntity = paasCommentModel.getByKey(commentEditDTO.getCommentId(),commentEditDTO.getCorpid());

            //记录编辑前的内容、图片、附件
            String oldContent = paasCommentEntity.getContent();
            JSONArray imageArray = JSONArray.parseArray(paasCommentEntity.getImage());
            int oldPicCount = Objects.nonNull(imageArray) ? imageArray.size() : 0;
            JSONArray attachmentArray = JSONArray.parseArray(paasCommentEntity.getAttachment());
            int oldAttaCount = Objects.nonNull(attachmentArray) ? attachmentArray.size() : 0;

            List<PaasAttachmentEntityExt> attachmentListEntity = commentEditDTO.getAttachmentList();
            if (Objects.equals(businessCommentEnum, BusinessCommentEnum.CUSTOMER_STAGE) || Objects.equals(businessCommentEnum, BusinessCommentEnum.SALE_STAGE)
                    || Objects.equals(businessCommentEnum, BusinessCommentEnum.CLUE_STAGE)|| Objects.equals(businessCommentEnum,BusinessCommentEnum.PAAS_STAGE)
                    || Objects.equals(businessCommentEnum, BusinessCommentEnum.CONTRACT_STAGE)) {
                Long dataId = commentEditDTO.getDataId();
                if (dataId != null) {
                    List<PaasAttachmentEntityExt> attachmentList = new ArrayList<>(attachmentListEntity);
                    if (CollectionsUtil.isNotEmpty(attachmentList)) {
                        String attachments = paasCommentModel.getByKey(commentEditDTO.getCommentId(), commentEditDTO.getCorpid()).getAttachment();
                        if (attachments != null) {
                            List<PaasAttachmentEntityExt> attachmentListExist = JSON.parseArray(attachments, PaasAttachmentEntityExt.class);
                                attachmentList.removeAll(attachmentListExist);
                        }
                        if(CollectionsUtil.isNotEmpty(attachmentList)) {
                            CabinetFileSaveDTO cabinetFileSaveDTO = new CabinetFileSaveDTO(attachmentList, businessType, dataId);
                            cabinetFileSaveDTO.setUserId(commentEditDTO.getUserId());
                            cabinetFileSaveDTO.setCorpid(commentEditDTO.getCorpid());
                            cabinetFileSaveDTO.setType(CabinetFileTypeEnum.NORMAL.getType());
                            cabinetFileService.saveCabinetFiles(cabinetFileSaveDTO);
                        }
                    }
                    stageDetailHelp.savaCommentLog( commentEditDTO.getCorpid(),  saasMark,  businessType,  dataId,  commentEditDTO,  commentEditDTO.getRefId(),
                            paasCommentEntity.getContent(),commentEditDTO.getContent());
                }
            }

            List<String> atUserIds = commentEditDTO.getAtUserIds();
            if (CollectionsUtil.isNotEmpty(atUserIds)) {
                atUserIds.remove(commentEditDTO.getRefUserId());
                paasCommentEntity.setAtUserId(JSON.toJSONString(atUserIds));
            } else {
                atUserIds = new ArrayList<>();
            }
            paasCommentEntity.setContent(commentEditDTO.getContent());
            paasCommentEntity.setImage(JSONArray.toJSONString(commentEditDTO.getImages()));
            paasCommentEntity.setAttachment(JSONArray.toJSONString(attachmentListEntity));
            paasCommentModel.updateContentByKey(paasCommentEntity);

            // 如果是回复，重新设置refId，因为回复的refId是上级的评论id
            commentEditDTO.setRefId(getRefIdByIsReply(commentEditDTO.isReply(),commentEditDTO.getRefId(),commentEditDTO.getCorpid()));

            Long refId =  commentEditDTO.getRefId();
            if ( Objects.equals(businessCommentEnum, BusinessCommentEnum.CUSTOMER_STAGE)   ) {
                CustomerStageLogEntity customerStageLogEntity = customerStageLogModel.getByKey(refId,commentEditDTO.getCorpid());
                refId = customerStageLogEntity.getDataId();
            }else if ( Objects.equals(businessCommentEnum, BusinessCommentEnum.SALE_STAGE) ){
                OpportunityStageLogEntity opportunityStageLogEntity = opportunityStageLogModel.getByKey(refId,commentEditDTO.getCorpid());
                refId = opportunityStageLogEntity.getDataId();
            }else if ( Objects.equals(businessCommentEnum, BusinessCommentEnum.CLUE_STAGE) ){
                ClueStageLogEntity clueStageLogEntity = clueStageLogModel.getByKey(refId,commentEditDTO.getCorpid());
                refId = clueStageLogEntity.getDataId();
            } else if (Objects.equals(businessCommentEnum, BusinessCommentEnum.CONTRACT_STAGE)) {
                // 合同阶段是个Paas字段，相关的阶段记录存储的Paas的StageLog表
                StageLogEntity stageLogEntity = stageLogModel.getByKey(refId, commentEditDTO.getCorpid());
                refId = stageLogEntity.getDataId();
            } else if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE) ){
                StageLogEntity stageLogEntity = stageLogModel.getByKey(refId,commentEditDTO.getCorpid());
                refId = stageLogEntity.getDataId();
            }
            commentAddVO.setCommentId(paasCommentEntity.getId());
            // 评论/艾特消息推送
            pushCommentEdit(commentEditDTO.getLoginUser(), businessType, refId, commentEditDTO.getCorpid(), atUserIds, CommentHelp.filterCommentContent(commentEditDTO.getContent()), businessCommentEnum);

            //老审批的评论需要记录日志
            if(Objects.equals(businessCommentEnum, BusinessCommentEnum.APPROVAL)){
                Runnable runnable = () -> {
                    try {
                        //编辑后的内容、图片、附件
                        String newContent = commentEditDTO.getContent();
                        int newPicCount = commentEditDTO.getImages().size();
                        int newAttaCount = commentEditDTO.getAttachmentList().size();
                        String corpid = commentEditDTO.getCorpid();

                        List<DetailLogPojo> detailArr = new ArrayList<>();
                        DetailLogPojo contentDetailLogPojo = new DetailLogPojo(null, DetailLogEnum.CONTENT_TEXT.getName(), oldContent, newContent);
                        detailArr.add(contentDetailLogPojo);
                        DetailLogPojo picDetailLogPojo = new DetailLogPojo(null, DetailLogEnum.PICTURE_COUNT.getName(), String.valueOf(oldPicCount), String.valueOf(newPicCount));
                        detailArr.add(picDetailLogPojo);
                        DetailLogPojo attaDetailLogPojo = new DetailLogPojo(null, DetailLogEnum.ATTACHMENT_COUNT.getName(), String.valueOf(oldAttaCount), String.valueOf(newAttaCount));
                        detailArr.add(attaDetailLogPojo);

                        PaasProcessTaskEntity processTaskEntity = paasProcessTaskModel.getByKey(commentEditDTO.getRefId().intValue(), corpid);
                        String creatorId = processTaskEntity.getCreatorId();
                        List<UserEntity> userEntityList = userModel.getByUserId(Collections.singletonList(creatorId), corpid);
                        PaasFormEntity paasFormEntityExt = proFormHelp.getPaasForm(processTaskEntity.getFormId(), processTaskEntity.getBusinessType(), corpid);
                        String title;
                        if (CollectionUtils.isEmpty(userEntityList)) {
                            title = "***"+ I18nMessageUtil.getMessage(CommonConstant.OF) + paasFormEntityExt.getName() + I18nMessageUtil.getMessage(I18nStringConstant.APPROVAL);
                        } else {
                            title = userEntityList.get(0).getName() + I18nMessageUtil.getMessage(CommonConstant.OF) + paasFormEntityExt.getName() + I18nMessageUtil.getMessage(I18nStringConstant.APPROVAL);
                        }
                        UserVO loginUser = commentEditDTO.getLoginUser();
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_EDIT_WORKFLOW_COMMENT), loginUser.getName());
                        mongoLogHelp.buildLog4DetailArr(detailArr, corpid, loginUser.getUserId(), loginUser.getName(), OperateModuleTypeEnum.APPROVAL, OperateTypeEnum.EDIT_APPROVE_COMMENT,null, title, memo, commentEditDTO.getHttpHeader());
                    } catch (XbbException e) {
                        log.error("com.xbongbong.paas.service.impl.PaasCommentServiceImpl.edit push or log: error");
                    }
                };
                logThreadPoolBeanConfig.sysLogThreadPool().execute(runnable);
            }

        } catch (Exception e) {
            LOG.error("paasFormData数据库查询数据出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return commentAddVO;
    }

    @Override
    public void pushCommentEdit(UserVO loginUser, Integer businessType, Long refId, String corpid, List<String> atUserIds, String content, BusinessCommentEnum businessCommentEnum) throws XbbException {
        if (Objects.isNull(businessCommentEnum)) {
            return;
        }
        PaasFormDataEntityExt paasFormDataEntityExt;
        if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
            paasFormDataEntityExt = paasFormDataModel.getByKey(refId, corpid);
        } else {
            paasFormDataEntityExt = saasGetHelp.getFormData(refId, corpid, businessType);
        }
        String createrId = null;
        Long appId = 0L;
        Long formId = 0L;
        Long menuId = 0L;
        if (Objects.isNull(paasFormDataEntityExt) && !Objects.equals(businessCommentEnum,BusinessCommentEnum.APPROVAL)) {
            return;
        } else if ( Objects.nonNull(paasFormDataEntityExt) && !Objects.equals(businessCommentEnum,BusinessCommentEnum.APPROVAL) ){
            createrId = paasFormDataEntityExt.getCreatorId();
            appId = paasFormDataEntityExt.getAppId();
            formId = paasFormDataEntityExt.getMenuId();
            menuId = paasFormDataEntityExt.getMenuId();
        }

        String userName = loginUser.getName();
        String pushTitle = "";
        String pushContent = "";
        PushTypeEnum pushTypeEnum = null;
        switch (businessCommentEnum) {
            case APPROVAL:
                PaasProcessDataEntity paasProcessDataEntity = paasProcessDataModel.getByTaskId(refId, corpid);
                if (paasProcessDataEntity == null) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_TASK_NOT_EXIST);
                }
                createrId = paasProcessDataEntity.getCreatorId();
                appId = paasProcessDataEntity.getAppId();
                formId = paasProcessDataEntity.getFormId();
                menuId = paasProcessDataEntity.getMenuId();
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("corpid", loginUser.getCorpid());
                param.put("del", 0);
                param.put("userId", createrId);
                List<UserEntity> userList = userModel.findEntitys(param);
                pushTitle = I18nMessageUtil.getMessage(ProcessPushConstant.PROCESS_COMMENT_TITLE);
                pushContent = String.format(I18nMessageUtil.getMessage(ProcessPushConstant.PROCESS_COMMENT_EDIT_CONTENT), userName, userList.isEmpty() ? "" : userList.get(0).getName());
                pushTypeEnum = PushTypeEnum.APPROVAL_COMMENT_EDIT;

                if (!Objects.equals(loginUser.getUserId(), createrId)) {
                    List<String> pushUserList = Collections.singletonList(createrId);
                    //PushRefTypePojo.Options options = new PushRefTypePojo.Options(appId, menuId, formId, refId, Collections.singletonList(refId), SaasMarkEnum.SAAS.getCode(), businessType, businessType);
                    Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    params.put("del", 0);
                    params.put("corpid", corpid);
                    params.put("taskId", paasProcessDataEntity.getTaskId());
                    param.put("nodeType", NodeTypeEnum.START_PROCESS_NODE.getNodeType());
                    params.put("orderByStr", " id DESC ");
                    List<PaasProcessNodeTaskEntityExt> nodeTaskList = paasProcessNodeTaskModel.findEntitys(params);
                    if (nodeTaskList.isEmpty()) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NODE_TASK_NOT_EXIST);
                    }

                    PushRefTypePojo.Options options = new PushRefTypePojo.Options(appId, menuId, formId, Collections.singletonList(refId), paasProcessDataEntity.getSaasMark(), paasProcessDataEntity.getBusinessType(), refId, nodeTaskList.get(0).getId(), ProcessTypeEnum.TODO.getValue());
                    MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(refId), 0, null, pushTitle, pushContent, null, options);
                    baseProducer.sendMessage(pushTypeEnum, messageRabbitMqDTO);
                }
                pushProcessComment(loginUser,refId,atUserIds);
                return;
            case WORK_ORDER:
                pushTitle = I18nMessageUtil.getMessage(WorkOrderPushConstant.WORK_ORDER_COMMENT_TITLE);
                pushContent = String.format(I18nMessageUtil.getMessage(WorkOrderPushConstant.PUSH_DYNAMIC_UPDATE), userName, paasFormDataEntityExt.getSerialNo());
                pushTypeEnum = PushTypeEnum.WORKORDER_DYNAMIC_UPDATE_PUSH;
                break;
            case CONTRACT_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(ContractStagePushConstant.CONTRACT_STAGE_COMMENT_EDIT_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.CONTRACT_STAGE_PUSH;
                break;
            case CUSTOMER_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(CustomerStagePushConstant.CUSTOMER_STAGE_COMMENT_EDIT_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.CUSTOMER_STAGE;
                break;
            case SALE_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(OpportunityStagePushConstant.OPPORTUNITY_STAGE_COMMENT_DEL_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.OPPORTUNITY_STAGE_PUSH;
                break;
            case CLUE_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(ClueStagePushConstant.CLUE_STAGE_COMMENT_DEL_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.CLUE_STAGE;
                break;
            case PAAS_STAGE:
                pushTitle = String.format(I18nMessageUtil.getMessage(PaasStagePushConstant.PAAS_STAGE_COMMENT_EDIT_TITLE), userName);
                pushContent = content;
                pushTypeEnum = PushTypeEnum.PAAS_STAGE;
                break;
            default:
                break;
        }
        if (!Objects.equals(loginUser.getUserId(), createrId)) {
            List<String> pushUserList = Collections.singletonList(createrId);
            Integer saasMark = SaasMarkEnum.SAAS.getCode();
            if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
                saasMark = SaasMarkEnum.PAAS.getCode();
            }
            PushRefTypePojo.Options options = new PushRefTypePojo.Options(appId, menuId, formId, refId, Collections.singletonList(refId), saasMark, businessType, businessType);
            if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
                PaasMenuEntity paasMenuEntity = paasMenuModel.getByKey(menuId, corpid);
                options.setName(Objects.nonNull(paasMenuEntity) ? paasMenuEntity.getName() : "");
            }
            MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(refId), 0, null, pushTitle, pushContent, null, options);
            if (Objects.equals(businessCommentEnum, BusinessCommentEnum.PAAS_STAGE)) {
                messageRabbitMqDTO.setPushTime(DateTimeUtil.getInt() + 10);
                messageService.delayPushDingtalkOAMessage(messageRabbitMqDTO, pushTypeEnum);
            } else {
                baseProducer.sendMessage(pushTypeEnum, messageRabbitMqDTO);
            }
        }
        atUserIds.remove(loginUser.getUserId());
        if (atUserIds.size() > 0) {
            // 评论艾特消息推送
            pushCommentAt(loginUser, refId, corpid, atUserIds, businessCommentEnum, paasFormDataEntityExt, content);
        }
    }

    @Override
    public JSONObject getWorkOrderDynamic(FormDataGetDTO formDataGetDTO) throws XbbException {
        JSONObject workOrderDynamicData = new JSONObject();
        String corpid = formDataGetDTO.getCorpid();
        Long dataId = formDataGetDTO.getDataId();
        try {
            BusinessCommentEnum businessCommentEnum = BusinessCommentEnum.getByBusinessType(formDataGetDTO.getBusinessType());
            if (businessCommentEnum == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018);
            }
            Map<String, Object> map = BeanUtil.convertBean2Map(formDataGetDTO, true);
            map.put("refId", dataId);
            map.put("type", businessCommentEnum.getCode());
            map.put("orderByStr", "add_time desc");
            List<PaasCommentEntityExt> list = paasCommentModel.list(map);
            if (list == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            if (list.size()>=200){
                throw  new XbbException(PrintErrorCodeEnum.API_ERROR_2320016, PrintErrorCodeEnum.API_ERROR_2320016.getMsg());
            }
            List<Long> refIdIn = new ArrayList<>();
            List<JSONObject> dynamicAll = new ArrayList<>();
            Map<Long, JSONObject> dynamic = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            list.forEach(item -> {
                refIdIn.add(item.getId());
                JSONObject comment = dealComment(item);
                dynamic.put(item.getId(), comment);
            });
            map.remove("refId");
            map.put("refIdIn", refIdIn);
            List<PaasCommentEntityExt> refComment = paasCommentModel.list(map);
            for (PaasCommentEntityExt item : refComment) {
                JSONObject jsonObject = dynamic.get(item.getRefId());
                JSONArray jsonArray = jsonObject.getJSONArray("list");
                JSONObject jsonObject1 = dealComment(item);
                jsonArray.add(jsonObject1);
                if (jsonArray.size() > 200) {
                    throw  new XbbException(PrintErrorCodeEnum.API_ERROR_2320015, PrintErrorCodeEnum.API_ERROR_2320015.getMsg());
                }
            }
            Collection<JSONObject> values = dynamic.values();
            workOrderDynamicData.put("workOrderDynamic",values);

        } catch (Exception e) {
            LOG.error("paasFormData数据库查询数据出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }

        return workOrderDynamicData;
    }

    @Override
    public ReplyListVO replyList(ReplyListDTO replyListDTO) throws XbbException {
        ReplyListVO replyListVO = new ReplyListVO();
        try {
            String corpid = replyListDTO.getCorpid();
            Long commentId = replyListDTO.getCommentId();

            Map<String,Object> paramMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            paramMap.put(StringConstant.CORPID,corpid);
            paramMap.put("refId",commentId);
            paramMap.put("type", BusinessCommentEnum.COMMENT_REPLY.getCode());
            paramMap.put("orderByStr","add_time asc");
            paramMap.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            List<PaasCommentEntityExt> replyList = paasCommentModel.findEntitys(paramMap);

            // 封装回复信息，便于前端展示
            this.packageReplyInfo(replyList,replyListDTO);
            replyListVO.setReplyList(replyList);
        }catch (Exception e){
            LOG.error("paasCommentService.replyList excepiont:{}",e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());        }
        return replyListVO;
    }

    /**
     *
     * @param item
     * @return
     */
    private JSONObject dealComment(PaasCommentEntityExt item) {
        JSONObject comment = new JSONObject();
        comment.put("addTime", item.getAddTime());
        comment.put("addTimeStr", item.getAddTimeStr());
        if (StringUtil.isNotEmpty(item.getAttachment())) {
            comment.put("attachment", item.getAttachment());
            comment.put("attachmentList", item.getAttachmentList());
        }
        comment.put("content", item.getContent());
        comment.put("userName", item.getUserName());
        if (StringUtil.isNotEmpty(item.getImage())) {
            comment.put("image", item.getImage());
            comment.put("imageList", item.getImageList());
        }
        comment.put("list",new JSONArray());
        return comment;
    }

    /**
     * 分别设置每条评论下的回复数量
     * @param corpid
     * @param commentList
     */
    private void eachSetReplyCount(String corpid,List<PaasCommentEntityExt> commentList){
        if (CollectionUtils.isEmpty(commentList)) {
            return;
        }
        List<Long> commentIdList = commentList.stream().map(item -> item.getId()).collect(Collectors.toList());
        Map<Long, Integer> replyCountMap = paasCommentModel.batchGetReplyCount(corpid, BusinessCommentEnum.COMMENT_REPLY.getCode(), commentIdList);
        commentList.stream().forEach(item -> {
            Integer count = replyCountMap.getOrDefault(item.getId(),0);
            item.setReplyCount(count);
        });
    }


    /**
     * 这里做转化是因为阶段推进器目前支持了回复的层级展示，回复类型的数据使用的refId是评论的id，这里需要取评论的refId
     * @param isReply
     * @param refId
     * @param corpid
     * @return
     */
    private Long getRefIdByIsReply(Boolean isReply,Long refId,String corpid){
        if (!isReply){
            return refId;
        }
        // 获取当前回复的上级评论
        PaasCommentEntity commentEntity= paasCommentModel.getByKey(refId,corpid);
        // 防止空指针
        if (commentEntity == null) {
            return -1L;
        }
        return commentEntity.getRefId();
    }


    /**
     * 封装回复信息
     * @param replyList 回复列表
     * @param replyListDTO 用于封装回复的atUserIdList属性
     */
    private void packageReplyInfo (List<PaasCommentEntityExt> replyList,ReplyListDTO replyListDTO ) throws XbbException {
        if (CollectionUtils.isEmpty(replyList)) {
            return;
        }

        // 设置回复简单信息
        this.eachSetReplySimpleInfo(replyList,replyListDTO);

        // 获取被@用户的简单信息
        this.eachSetReplyAtUserInfo(replyList,replyListDTO);

        // 回复添加权限信息
        this.eachSetReplyPermission(replyListDTO,replyList);
    }

    /**
     * 每个回复设置编辑和删除权限，只有本人和超管才能编辑和删除
     * @param replyListDTO
     * @param replyList
     */
    private void eachSetReplyPermission(ReplyListDTO replyListDTO , List<PaasCommentEntityExt> replyList){
        if (CollectionUtils.isEmpty(replyList)) {
            return;
        }

        UserVO loginUser = replyListDTO.getLoginUser();
        boolean iaAdmin = loginUser.isAdmin();

        for (PaasCommentEntityExt reply : replyList) {
            String createId = reply.getUserId();
            JSONArray permissionAry = new JSONArray();
            if (iaAdmin || Objects.equals(loginUser.getUserId(),createId)){
                permissionAry.add("edit");
                permissionAry.add("delete");
            }
            reply.setPermissionSet(permissionAry);
        }
    }

    /**
     * 获取回复的atUserId的用户详细信息
     * @param replyList
     * @param replyListDTO
     * @throws XbbException
     */
    private void eachSetReplyAtUserInfo(List<PaasCommentEntityExt> replyList,ReplyListDTO replyListDTO) throws XbbException {

        if (CollectionUtils.isEmpty(replyList)) {
            return;
        }

        UserGetDTO userGetDTO = new UserGetDTO();
        BeanUtil.copyProperties(replyListDTO,userGetDTO);

        // 收集回复的atUserId为一个set
        Set<String> atUserIdSet = new HashSet<>();
        for (PaasCommentEntityExt reply : replyList) {
            List<String> userIdList = JSONArray.parseArray(reply.getAtUserId()).toJavaList(String.class);
            if (CollectionUtils.isEmpty(userIdList)) {
                continue;
            }
            atUserIdSet.addAll(userIdList);
        }

        // 根据收集的set一次性查询出所有的用户信息
        List<String> atUserIdList = new ArrayList<>(atUserIdSet);
        userGetDTO.setTargetUserId(atUserIdList);
        UserGetVO userGetVO = userService.getUserInfoByTargetUserId(userGetDTO);
        List<UserVO> userVOList = userGetVO.getUserList();

        // userListVO转化成map方便下面遍历获取
        Map<String, UserVO> userVOMap = userVOList.stream().collect(Collectors.toMap(item -> item.getUserId(), item -> item));

        // 设置回复的atUserIdList属性
        for (PaasCommentEntityExt reply : replyList) {
            List<String> userIdList = JSONArray.parseArray(reply.getAtUserId()).toJavaList(String.class);

            JSONArray atUserInfoJsonArray = new JSONArray();
            if (CollectionUtils.isEmpty(userIdList)) {
                reply.setAtUserIdList(atUserInfoJsonArray);
                continue;
            }


            List<Object> atUserInfoList = userIdList.stream().map(userId -> userVOMap.get(userId)).filter(userinfo -> Objects.nonNull(userinfo))
                    .map(userinfo -> {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("avatar", userinfo.getAvatar());
                        jsonObject.put("id", String.valueOf(userinfo.getUserId()));
                        jsonObject.put("name", userinfo.getName());
                        return jsonObject;
                    }).collect(Collectors.toList());

            // 这里故意套一层是为了适配之前就有的属性数据类型
            atUserInfoJsonArray.addAll(atUserInfoList);

            reply.setAtUserIdList(atUserInfoJsonArray);
        }

    }

    /**
     * 设置回复的的一些简单信息，用户前端展示
     * @param replyList
     * @param replyListDTO
     */
    private void eachSetReplySimpleInfo(List<PaasCommentEntityExt> replyList,ReplyListDTO replyListDTO){

        if (CollectionUtils.isEmpty(replyList)) {
            return;
        }

        // list 转 map 方便下面根据回复id获取回复数据
        Map<Long,PaasCommentEntityExt> replyMap = replyList.stream().collect(Collectors.toMap(reply -> reply.getId(), reply -> reply));

        for (PaasCommentEntityExt reply : replyList) {
            // 创建时间格式化
            reply.setAddTimeStr(DateTimeUtil.getStringEpochSecond(reply.getAddTime(), DateTimeUtil.SDF));

            // 设置上级回复内容
            Long replyParentId = reply.getReplyParentId();
            if (replyParentId == null || Objects.equals(replyParentId,0L)){
                continue;
            }

            PaasCommentEntityExt parentReply = replyMap.get(replyParentId);
            if (parentReply == null || Objects.equals(parentReply.getDel(), DelEnum.DELETE.getDel())) {
                reply.setParentReplyContent(I18nMessageUtil.getMessage(PaasCommentConstant.PARENT_REPLY_IS_DEL));
            }else {
                reply.setParentReplyContent(parentReply.getContent());
            }
        }
    }
}
